相同内存地址的两个不同值

L.L*_*iet 16 c++

#include <iostream>
using namespace std;

int main() {
    const int N = 22;
    int * pN = const_cast<int*>(&N);
    *pN = 33;
    cout << N << '\t' << &N << endl;
    cout << *pN << '\t' << pN << endl;
}
Run Code Online (Sandbox Code Playgroud)

产量

22 0x22ff74

33 0x22ff74

为什么同一地址有两个不同的值?

Eri*_*ert 22

为什么同一地址有两个不同的数据?

没有.允许编译器优化对const的任何提及,就好像你已经在其中编写了编译时值.

请注意,编译器也允许生成在运行它时擦除硬盘的代码,如果你做了一些令人讨厌的技巧,比如写入为consts保留的内存.

  • @thb:或者,"未定义的行为可能导致您的Web浏览器安全策略停止工作并允许任意恶意代码在浏览器中运行",因为我也导致了该错误.我们需要一些方法来表征**它有多糟糕**.你更喜欢什么? (3认同)
  • @thb:栗子的重点不是描述可能的场景,而是表明可能未定义行为的*幅度*;这是说*真的,任何事情都可能发生*的方便方式。您是否更愿意说,“允许未定义的行为将私有变量的内容写入屏幕内存*?因为我*已经*编写了意外覆盖常量内存的程序。 (2认同)
  • @thb:哦,绝对试验可以深入了解实现细节.但是从这种经历中学到太多东西是可能的; 我在这里看到的问题基本上是"当我做的时候为什么没有C++段错误..."当你做坏事时知道一个实现崩溃不应该给出其他实现的不安全感.过度概括当你做坏事时发生的最糟糕的事情是崩溃,就像在C#或Java中那样,导致低估了可能的后果. (2认同)
  • @thb:另外,您注意到 C 是“面向硬件的”,我同意,但认为所有 C 实现都会对未定义行为产生*直接、毫不奇怪*的后果是假设优化策略在 1970 年代停止。我最喜欢的关于 UB 在现代编译器中的后果的文章是 https://blogs.msdn.microsoft.com/oldnewthing/20140627-00/?p=633 -- Raymond 指出 UB 会导致 *effects 及时向后移动*. 这是一种*可能的*行为,因此不为 UB 所禁止。 (2认同)

GMa*_*ckG 10

你在行上得到了未定义的行为*pN = 33;,因为你正在修改一个const值.任何事情都可能发生.不要这样做.


但可能,您的编译器只是进行了优化.在线:

cout << N << '\t' << &N << endl;
Run Code Online (Sandbox Code Playgroud)

它知道N是一个值为22的常量表达式,所以只需将该行更改为:

cout << 22 << '\t' << &N << endl;
Run Code Online (Sandbox Code Playgroud)

在下一行中,您将获取地址的值,并将N其"设置"为33.(但实际上,您所做的只是删除有关程序状态的任何保证.)


bdo*_*lan 5

通过声明它N是const,您已承诺不会对其进行修改。然后您去修改它。这打破了编译器所做的假设之一,结果,程序的行为不正确。

这被称为“未定义行为”-违反该语言的假设后,程序的行为将完全未定义。它不需要产生该输出-它既可以33为或产生,也可以为42崩溃,擦除硬盘驱动器或通过鼻道传唤的恶魔产生。因此,请勿修改const值:)