修改const int时gcc -O2标志会产生影响

时间:2014-02-03 05:29:15

标签: c gcc

我知道在C中我们可以通过指针修改'const int'。但是在编译程序时我在gcc中启用了'-O2'标志,并且const int无法修改该值,所以只想知道gcc优化标志如何影响修改'const int'。

以下是示例应用程序test.c

#include <stdio.h>
#include <stdlib.h>

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

这种好奇心让我写下这个问题。

3 个答案:

答案 0 :(得分:1)

修改声明为const的变量是未定义的行为。未定义的行为是......未定义的;换句话说,编译器可以执行任何操作包括,假设未定义的行为实际上没有发生。

在这种情况下,编译器可以通过假设它永远不会改变来优化对const int i的访问;允许编译器在i的调用中插入已知的初始值printf。实际上,它可以预编译要在编译时输出的字符串,因为它知道printf应该做什么。

你可以通过指针绕过const声明,这是不正确的。如果变量最初声明为const,则尝试修改它无效。你可以做的是创建一个指向可变变量的const指针,然后通过将其抛弃来绕过指针的const。由于原始变量不是const,这是合法的(虽然通常不是一个好主意。)

(强制性标准参考:§6.7.3/ 6:“如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为未定义。 “)

答案 1 :(得分:1)

  

我知道在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;
             ^      ~~

答案 2 :(得分:0)

此行是约束违规

int *iPtr = &i;

&i的类型为const int *。当前C标准的第6.5.16.1/1节(&#34;简单赋值&#34;)列出了代码的行为,其中列出了赋值的约束。

这些约束的一部分是左操作数不允许指向非限定类型的指针,而右操作数是指向限定类型​​的指针。

如果编译器在标准兼容模式下运行,则必须提供诊断消息。它可能无法生成可执行文件。如果编译器继续执行任何其他操作,则标准不再涵盖该行为。 (换句话说,该程序具有完整的未定义行为)。

NB。其他答案提及&#34;修改const对象&#34;但是这与在任何修改对象的尝试之前发生约束违规无关;并且在违反约束条件后所有投注均已关闭。