我们可以通过指针改变用const定义的对象的值吗?

Shw*_*eta 28 c const undefined-behavior

#include <stdio.h>
int main()
{
    const int a = 12;
    int *p;
    p = &a;
    *p = 70;
}
Run Code Online (Sandbox Code Playgroud)

它会起作用吗?

Cra*_*rks 32

它是"未定义的行为",意味着基于标准,您无法预测尝试此操作时会发生什么.根据特定的机器,编译器和程序状态,它可能会执行不同的操作.

在这种情况下,最常发生的是答案是肯定的.变量const或非变量只是内存中的一个位置,您可以破坏const的规则并简单地覆盖它.(当然,如果程序的其他部分依赖于其const数据是恒定的,这将导致严重的错误!)

但是在某些情况下 - 最常见的是const static数据 - 编译器可能会将这些变量放在只读的内存区域中.例如,MSVC通常将const static int放在可执行文件的.text段中,这意味着如果你尝试写入操作系统将引发保护错误,程序将崩溃.

在编译器和机器的其他组合中,可能会发生完全不同的事情.您可以肯定的一件事是,这种模式会让任何必须阅读您的代码的人烦恼.


Jer*_*myP 14

这是未定义的行为.证明:

/* program.c */

int main()
{
        const int a = 12;
        int* p;
        p = &a;
        *p = 70;
        printf("%d\n", a);
        return 0;
}


gcc program.c
Run Code Online (Sandbox Code Playgroud)

并运行它.输出为70(gcc 4.3)

然后像这样编译:

gcc -O2 program.c
Run Code Online (Sandbox Code Playgroud)

并运行它.输出将是12.当它进行优化时,编译器可能会将12加载到寄存器中,并且在需要访问printf时不会再次加载它,因为它"知道"a不能更改.

  • 有趣的是,当我运行这个程序时,输出是42. (9认同)
  • @abelenky:是的,但你是否停下来思考问题是什么?也许你应该建立一台计算机来找出答案. (6认同)
  • UB 的证明将引用标准,而不是检查代码输出 (2认同)

Mic*_*kis 11

const通过指针修改限定对象会调用未定义的行为,结果就是这样.它可能是你期望的东西,即.如果已放入,则前一个值不变.text,等等.

  • 另一个可能的结果是"某些表达式表现得好像'a`仍然是12,而其他表现就好像'a`现在是70",这可能是也可能不是"你期望的东西". (4认同)

Ale*_*gen 6

它确实适用于gcc.它不喜欢它:

test.c:6:警告:赋值从指针目标类型中丢弃限定符

但是执行时价值确实发生了变化.我不会指出明显的禁忌......