隐藏的储藏室在哪里
Where is the hidden storage?
我对以下情况有点困惑
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
可能会使编译器以预期的方式做出更多响应。请记住,它仍然是未定义的行为,尽管如此
- C++我需要了解在哪里使用指针和双指针
- 未定义的引用在哪里
- 谷歌测试中的期望值存储在哪里
- 尽管遵循了规则,内存泄漏在哪里
- 静态数据成员模板专用化的实例化点在哪里
- 在哪里放置我的函数?进入我的母语 Gui 还是进入我的演示者?
- 在哪里声明结构运算符重载
- C++ 中的自定义异常:在哪里定义它们?
- 常量参数存储在哪里 (C++)?
- 如何在 c++ 中确定一条指令(以字节为单位)在哪里结束,另一条指令从哪里开始?
- 此递归函数的每次迭代的值存储在哪里?
- 如何告诉本机节点模块所需的dll存储在哪里?
- 在哪里存储跨平台C++应用存储?
- C++泛型类错误,问题出在哪里?
- 在标准中,模板参数的语法在哪里定义,例如,'std::function<int(char)>'?
- 将类作为主要参数的语法在哪里需要?
- 模板参数在 C++ 中存储在哪里?
- 我的重复检查代码中的错误究竟在哪里?
- 在哪里可以找到 std::bitset 的数据成员?
- 隐藏的储藏室在哪里