隐藏存储在哪里?

时间:2011-08-26 09:50:06

标签: c++

我对以下情况感到困惑

const char c = 'C';
char * p = const_cast<char *>(&c);

*p = 'K';
cout << " c = " << c << endl;
cout << " *p = " << *p << endl;

printf("c's address      : %u\n", &c);
printf("P is pointing to : %u\n", p);

执行时输出如下

c = C
*p = K
c's address      : 3221180271
P is pointing to : 3221180271

在这里我可以观察到'&amp; c'和'p'在内存中具有相同的地址。

那么'p'能够存储与'c'不同的值的隐藏机制是什么,而两者在内存中共享相同的地址空间?

4 个答案:

答案 0 :(得分:11)

没有“隐藏存储”。这些行

const char c = 'C'; 
char * p = const_cast<char *>(&c); // NO!

严重违反const-correctness。您正在创建一个非const指针,指向最初为const的内容。 不要那样做。虽然演员本身很好,但是如果你试图取消引用p它会调用未定义的行为,这意味着任何东西都可以发生,包括你刚刚描述的行为。

话虽如此,正在发生的事情是编译器是folding the constant c,因此第一个cout语句打印出C。因此,编译器可能将cout语句转换为:

cout << " c = " << 'C' << endl; // Note literal 'C' instead of variable c
cout << " *p = " << *p << endl;

因此,当第二个cout语句通过解除引用c来反映p的新值时,第一个cout语句不会受到影响。

第一个cout没有受到影响,因为编译器认为c的值永远不会改变(毕竟它是const)。有了这个假设,编译器就用常量值替换了变量访问。

当你这样做时,你违反了编译器的假设:

*p = 'K'; // NO!

由于p指向常量c,您刚刚将其更改为K,为您提供了所见的行为。

答案 1 :(得分:5)

const char c = 'C';
char * p = const_cast<char *>(&c);

*p = 'K';

这是未定义的行为。如果对象最初为const,则即使在const_cast之后也无法写入该对象。当您处于未定义行为的范围时,对于代码执行什么以及如何执行操作没有多大帮助。

答案 2 :(得分:1)

其他人已经解释说这是未定义的行为。幕后可能发生的是编译器发现c是const,因此允许将其值缓存在寄存器中。当您稍后读取c的值以将其打印出来时,编译器不会打扰从内存中取出它(它是const,所以它不能更改,对吧?),但只是使用而是缓存的值。

答案 3 :(得分:1)

未定义的行为。允许编译器优化(例如保留在寄存器中)它知道不可变的事物。

标记char volatile可能会使编译器以预期的方式响应更多。请记住,它仍然是未定义的行为