我知道在C中我们可以通过指针修改’const int’。 但是在编译程序时我在gcc中启用了’-O2’标志,并且const int无法修改该值,所以只想知道gcc优化标志如何影响修改’const int’。
这是示例应用程序test.c
#include #include int main(int ac, char *av[]) { const int i = 888; printf("i is %d n", i); int *iPtr = &i; *iPtr = 100; printf("i is %d n", i); return 0; } gcc -Wall -g -o test test.c ./test i is 888 i is 100 gcc -Wall -g -O2 -o test test.c i is 888 i is 888
这种好奇心让我写下这个问题。
我知道在C中我们可以通过指针修改’const int’。
不,那是错的。 C语言标准明确指出修改const
对象是“未定义的行为”。 这意味着任何事情都可能发生 – 代码可能会成功,它可能会崩溃,它可能会破坏你的硬盘,或让恶魔飞出你的鼻子。 所有这些行为都被认为是合法的。 因此,行为根据编译器的优化级别而变化的事实也是完全合法的。
任何有价值的编译器都会警告你这件事。 使用默认的编译器选项,GCC在我尝试编译代码时有用地告诉我:
$ gcc test.c test.c: In function 'main': test.c:8:21: warning: initialization discards 'const' qualifier from pointer target type [enabled by default]
Clang类似:
$ clang test.c test.c:8:14: warning: initializing 'int *' with an expression of type 'const int *' discards qualifiers [-Wincompatible-pointer-types-discards-qualifiers] int *iPtr = &i; ^ ~~
修改声明为const
的变量是未定义的行为。 未定义的行为是……未定义的; 换句话说,编译器可以做任何事情, 包括假设未实际发生未定义的行为。
在这种情况下,编译器可以通过假设它永远不会改变来优化对const int i
的访问; 允许编译器在对printf
的调用中插入i
的已知初始值。 实际上,它可以预编译要在编译时输出的字符串,因为它知道printf
应该做什么。
你可以通过指针绕过const
声明,这是不正确的。 如果变量最初声明为const
,则尝试修改它无效。 你可以做的是创建一个指向可变变量的const
指针,然后通过将其抛弃来绕过指针的const
。 由于原始变量不是const
,这是合法的(虽然通常不是一个好主意。)
(强制性标准参考:§6.7.3/ 6:“如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为未定义。”)
此行是违反约束 :
int *iPtr = &i;
&i
的类型是const int *
。 当前C标准(“简单赋值”)的6.5.16.1/1部分涵盖了代码的行为,其中列出了赋值的约束。
这些约束的一部分是左操作数不允许指向非限定类型的指针,而右操作数是指向限定类型的指针。
如果编译器在标准兼容模式下运行,则它必须提供诊断消息。 它可能无法生成可执行文件。 如果编译器继续执行任何其他操作,则标准不再涵盖该行为。 (换句话说,该程序具有完整的未定义行为)。
NB。 其他答案提到“修改const对象”,但是这与在任何修改对象的尝试之前发生约束违规无关; 并且在违反约束后所有投注均已关闭。
以上就是c/c++开发分享修改const int时gcc -O2标志会产生影响相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/522484.html