C 编译器行为不匹配

Đum*_*lav 1 c pointers constants

我编写了以下代码以测试它是否可以通过指针a修改常量c。我已经在 Clang、VC 和 GCC 编译器中对其进行了测试,并观察到 ​​VC 和 GCC 代码都按我的预期工作,它将 6 打印到标准输出,而当我用 Clang 编译它时,该值没有被修改,而 5打印到标准输出。

#include <stdio.h>

int main(void) {
  const int c = 5;
  int* a  = (int*) &c;
  *a = 6;
  printf("%d", c);
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我想知道对此是否有任何众所周知的解释,或者它与编译器的内部结构和其他难以分析的东西有关。提前谢谢大家!

Ant*_*ala 6

是的。它被称为未定义行为C11 6.7.3p6

  1. 如果尝试通过使用具有非 const 限定类型的左值来修改由 const 限定类型定义的对象,则行为未定义。

未定义的行为解释为

  1. 未定义的行为

    在使用不可移植或错误的程序结构或错误数据时的行为,本国际标准对此没有强加要求

  2. 注意:可能的未定义行为的范围从完全忽略具有不可预测结果的情况,在翻译或程序执行期间以环境特征的文件化方式(有或没有发布诊断消息),到终止翻译或执行(有诊断消息的发布)。

(强调我的)


在未启用优化的情况下编译与购买法拉利并始终仅以一档行驶相同。如果你使用gcc和编译会发生什么-O3

使用-O3我的 GCC 生成的代码相当于

#include <stdio.h>

int main(void) {
    printf("%d", 5);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

那么这个程序怎么样:

#include <stdio.h>

int main(void) {
    const char *foo = "Hello world!";
    char *bar = (char*)foo;
    bar[0] = 'C';
    printf("%s\n", foo);
}
Run Code Online (Sandbox Code Playgroud)

使用我的 GCC,-O3它崩溃了。但是如果你使用 Clang,它会打印Hello world!......如果你查看程序集 Clang 发现它可以优化为

 int main(void) {
     puts("Hello world!");
 }
Run Code Online (Sandbox Code Playgroud)