有这样的代码:
#include <iostream>
int main(){
const int a = 2;
int* ptr = (int*)&a;
*ptr = 3;
std::cout << &a << " " << ptr << " " << a << " " << *ptr << std::endl;
return 0;
}
结果:
0xbf88d51c 0xbf88d51c 2 3
为什么这两个值有所不同?这是怎么回事?
答案 0 :(得分:6)
int* ptr = (int*)&a;
这很危险(但这本身并不会调用UB)。但是这个,
*ptr = 3;
这会调用未定义的行为(UB),因为您尝试修改指向const
的{{1}}对象。 UB意味着任何事都可能发生。请注意,ptr
确实是一个const对象。
§7.1.5.1/ 4(C ++ 03)说,
除了可以修改声明为mutable(7.1.1)的任何类成员之外,任何在其生命周期内修改const对象的尝试(3.8)都会导致未定义的行为。
a
答案 1 :(得分:3)
不要做这样的事情。这是未定义的行为。
如果你撒谎到编译器,它将报复(c)
答案 2 :(得分:1)
我有一个假设,我没有测试过:
编译器为(0xbf88d51c)留出一个地址,并用2.填充它.int * ptr设置为该地址,* ptr = 3将3放在该地址。所以* ptr现在指向一个3.但是当它遇到值a时,编译器硬编码为“2”,就像你说#define a 2
一样。
验证的一种方法是提取生成的汇编代码。
顺便说一句,我知道这是不确定的行为,但那又怎样? OP询问为什么会这样。
答案 3 :(得分:1)
那是因为编译器用... " " << a << " " ...
替换... " " << 2 << " " ...
。
这样做是为了避免在已经知道的情况下从内存中读取a
的值,常量并且可以直接添加到汇编指令中。