隐藏的储藏室在哪里

Where is the hidden storage?

本文关键字:在哪里 储藏室 隐藏      更新时间:2023-10-16

我对以下情况有点困惑

const char c = 'C';
char * p = const_cast<char *>(&c);
*p = 'K';
cout << " c = " << c << endl;
cout << " *p = " << *p << endl;
printf("c's address      : %un", &c);
printf("P is pointing to : %un", p);

在执行时输出如下

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

在这里我可以观察到;c’和p’在存储器中具有相同地址。

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

没有"隐藏存储"。这些线路

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

严重违反const-正确性。您正在创建一个非const指针,指向最初为const的内容永远不要那样做虽然强制转换本身很好,但如果您尝试取消引用p,它将调用未定义的行为,这意味着任何事情都可能发生,包括您刚才描述的行为。

也就是说,编译器正在折叠常量c,以便第一个cout语句打印出C。因此编译器可能将cout语句转换为以下语句:

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

因此,虽然第二个cout语句通过取消引用p来反映c的新值,但第一个cout语句不受影响。

第一个cout没有受到影响,因为编译器认为c的值永远不会改变(毕竟是const(。在这种假设下,编译器将变量访问替换为常数值本身。

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

*p = 'K'; // NO!

因为p指向常数c,而您刚刚将其更改为K,从而得到您所看到的行为。

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

这是未定义的行为。如果一个对象最初是const,则即使在const_cast之后,也无法对其进行写入。当你处于未定义行为的领域时,对代码做什么以及如何做没有多大帮助。

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

未定义的行为。编译器被允许优化(例如保存在寄存器中(它知道是不可变的东西。

标记字符volatile可能会使编译器以预期的方式做出更多响应。请记住,它仍然是未定义的行为,尽管如此