c++ 编译器是否保护 const 内存地址免受任何更改?

Does c++ compiler protect const memory address from any change?

我想证明没有所谓的(受保护的内存地址),整个故事只是关于编译器,或者 OS,或者托管应用程序是什么应用程序 运行 只是对托管应用程序发送到其上级进程的读写请求进行一些检查,而这个上级应用程序或任何你称之为它的东西决定这个子进程是否有权读取或写入这个特定的内存位置,但这个 c++ 代码没有'在这个本质上工作,所以为什么:

#include <iostream>
int main()
{
    const int x = 10;
    std::cout << &x << std::endl; // So i can view address of x
    std::cout << "x Before is equal "<< x <<std::endl;

    int y ;
    std:: cin >> std::hex >>y;

    int *pinter = (int*)y ;
    *pinter = 20;
    std::cout << "x After is equal "<< x <<std::endl;
}

这段代码应该绕过 c++ 编译器将 x 变量类型设置为 const int 的概念,这样既不指向变量的指针(不像 C 中指向常量的指针可以更改常量的值),对变量的引用也不能更改变量,因此这段代码应该获取变量 x 的地址(当然是在它被打印出来之后),然后一个指针完成剩下的工作,所以我搞砸了在这里,因为它接缝就像这个内存位置是硬件保护的(我知道它不是但我很困惑)

This code is supposed to get around the concept of c++ compiler setting x variable type to const int so that [...]

你可以打破语言规则,但你的代码不是有效的 C++。您不得修改符合 const 条件的内容。如果你这样做,你有未定义的行为。由于编译器是用来编译有效的 C++,因此它们没有义务对无效代码做任何有意义的事情,结果可以是任何东西也可以什么都不是。

正如评论中所说:

const与硬件或内存无关。这是您和您的编译器之间的协议,而您违反了该协议。作为奖励,你的编译器会对你的代码做任何事情,但不一定是你所期望的。

您试图通过在运行时进行修改来欺骗编译器,这样在编译时编译器就不知道您将修改 const。但是,您确实将 x 声明为 const,因此编译器将假定其值不会更改。如果您仍然修改 x 的值,任何事情都可能发生。

PS:人们经常想到 "proove" private 不是真正的隐私,cosnt 不是真正的 const和类似的。问题是:这些工具应该可以帮助您减少错误并编写更清晰的代码。如果您努力尝试绕过这些设施,您将设法做到这一点(有时甚至不调用 UB)。然而,这 "prooves" 除了可能搬起石头砸自己的脚之外别无他法。 C++ 不是 Java,它不会握住你的手,并试图防止你犯下每一个可能的错误。在这方面,C++ 更接近 Python "we are all constenting adults here".

常量提供给: 1.注释该值不应更改 2.允许编译器更好地优化代码,因为它不应该被更改。

您不必跳过所有这些环节,您可以只使用“const_cast”来更改常量。

编译器“帮助”你强制执行常量,但正如你所展示的,有很多方法可以绕过它。如果您要更改 const 值,将产生 UB。

不起作用的原因(除了 UB,编译器可能会优化代码,知道 xconst)可能是因为如果你在 64 位系统上 运行,int y 不能保存 x 的地址。该地址很可能是设置了前 32 位之一的 64 位地址 - 而您的 int 很可能是 32 位。

使用正确的类型来存储地址并生成 x volatile const 并且您仍将拥有 UB - 但它可能只是 work期待。

#include <cstdint>
#include <iostream>

int main()
{
    volatile const int x = 10;    

    std::cout << "x Before is equal "<< x <<std::endl;

    std::uintptr_t y = (std::uintptr_t) &x;

    int *pinter = (int*) y;
    *pinter = 20;

    std::cout << "x After is equal "<< x <<std::endl;
}