const的未定义行为

时间:2014-02-14 22:54:05

标签: c++ c

我从没想过我会问这个问题,但我不知道为什么会这样。

const int a = 3; 
int *ptr;
ptr = (int*)( &a );
printf( "A=%d\n", &a );
*ptr = 5; 
printf( "A=%d\n", ptr );
printf( "A=%d\n", a );
printf( "A=%d\n", *ptr );

输出

A=6945404
A=6945404
A=3
A=5

这怎么可能发生?一个内存位置如何保存两个不同的值?我四处搜索,我发现未定义的行为未定义。那没有任何意义。必须有解释。

修改

我明白了,Marks回答很有意义,但我仍然想知道const被添加到语言中,以便用户不会无意中更改该值。我得到那些旧的编译器允许你这样做,但我在VS 2012上试过这个并且我得到了同样的行为。然后再次haccks说,一个内存位置不能保存它看起来像的两个值,那么第二个值存储在哪里?

4 个答案:

答案 0 :(得分:11)

优化程序可以确定a是一个常量值,并用文字3替换对它的任何引用。这就解释了你所看到的,虽然不能保证实际发生了什么。您需要研究生成的程序集输出。

答案 1 :(得分:4)

通过非const指针修改const变量会导致未定义的行为。最优秀的是,优化器会替换此行中的原始值:

printf( "A=%d\n", a );

查看反汇编以验证这一点。

C标准,第6.7.3节,第6段[ISO / IEC 9899:2011],规定: 如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为是未定义的。

答案 2 :(得分:1)

事实上,你的程序会调用未定义的行为,原因有两个:
1.您正在使用错误的说明符%d打印地址。正确的说明符是%p 2.您正在使用const说明符修改变量。

如果行为未定义,则可能发生任何事情。您可能会得到预期或意外的结果 标准说它;

3.4.3未定义的行为

  

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

答案 3 :(得分:1)

问题是ptr的类型是“指向int的指针”而不是“指向const int的指针”。 然后,您将'a'(一个const int)的地址转换为“指向int的类型”并将该地址存储在ptr中。这样做的结果是你正在抛弃const变量的常量。

这会导致未定义的行为,因此您的结果可能因编译器而异。

编译器可以在程序ROM中存储'a',因为它知道'a'是一个永远不能改变的const值。当你撒谎到编译器并抛弃'a'的常量以便你可以通过ptr修改它时,ptr实际修改'a'的值可能是无效的,因为该数据可能存储在程序ROM中。这次编译器决定将ptr指向另一个具有不同值的位置,而不是让你崩溃。但是由于这种行为未定义,所以可能发生了任何事情。