用指针改变常量对象的值

时间:2011-09-29 13:37:18

标签: c++

有这样的代码:

#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

为什么这两个值有所不同?这是怎么回事?

4 个答案:

答案 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的值,常量并且可以直接添加到汇编指令中。