更改const 变量的值的问题是编译器不会期望发生这种情况。考虑这段代码:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", a);
为什么编译器会在最后一条语句中读取a?编译器知道a 是12 并且因为它是const,所以它永远不会改变。所以优化器可能会将上面的代码转换成这样:
const int a = 12;
int * p = &a;
*p = 70;
printf("%d\n", 12);
这可能会导致奇怪的问题。例如。代码在没有优化的调试版本中可能会按需要运行,但在经过优化的发布版本中会失败。
实际上,一个好的优化器可能会将整个代码转换成这样:
printf("%d\n", 12);
因为之前的所有其他代码在编译器眼中都没有影响。省略没有效果的代码也不会影响整个程序。
另一方面,一个体面的编译器会识别出你的代码有问题并警告你,因为
int * p = &a;
实际上是错误的。正确的是:
const int * p = &a;
因为p 不是指向int 的指针,它是指向const int 的指针,当这样声明时,下一行将导致硬编译错误。
要消除警告,您必须强制转换:
int * p = (int *)&a;
更好的编译器会识别出这种转换违反了const 的承诺,并指示优化器不要将a 视为const。
如您所见,编译器的质量、功能和设置将最终决定您可以期待什么行为。这意味着相同的代码在不同的平台上或在同一平台上使用不同的编译器时可能会表现出不同的行为。
如果 C 标准为这种情况定义了一个行为,所有编译器都必须实现它,无论标准定义什么,它都很难实现,给每个想要编写一个编译器。即使标准刚刚说“这是禁止的”,所有编译器都必须执行复杂的数据流分析才能强制执行此规则。所以标准只是没有定义它。它定义了const 的值不能更改,如果您无论如何都找到了更改它们的方法,那么您将无法依赖任何行为。