我想证明没有什么所谓的(A protected memory address),整个故事只是关于编译器,或者操作系统,或者托管应用运行的任何应用程序只是对托管应用向其上级进程发送的读写请求进行一些检查,然后这个上级应用或者不管你怎么称呼它,决定这个子进程是否有权对这个特定的内存位置进行读写,但是这段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变量类型设置为 "x "的概念。const int 所以,无论是指向变量的指针(不像在C语言中,指向常量的指针可以改变常量的值)还是对变量的引用都不能改变变量,所以这段代码应该得到变量x的地址(当然是在它被打印出来之后),然后一个指针来做剩下的工作,所以我在这里搞砸了,因为它看起来像这个内存位置是硬件保护的(我知道它不是,但我很困惑)。
这段代码应该是为了绕过c++编译器将x变量类型设置为const int的概念,这样[...]。
你可以打破语言的规则,但你的代码不是有效的C++。你不得修改被限定为 const
. 如果你这样做,你就会有未定义的行为。因为编译器是用来编译有效的C++的,它们并没有被要求对非有效的代码做任何有意义的事情,结果可以是任何东西,也可以是没有。
正如在评论中已经说过的。
const
与硬件和内存无关 这是你和你的编译器之间的协议,你违反了这个协议。作为奖励,你的编译器会对你的代码做任何事情,但不一定是你期望的。
你试图欺骗编译器,在运行时进行修改,使编译器在编译时无法知道你将修改一个 const
. 但是,你确实宣布 x
作为 const
所以编译器会认为它的值不会改变。如果你仍然修改 x
任何事情都有可能发生。
PS:相当频繁地有人想出一些小技巧来 "证明"。private
并不是真正的隐私。cosnt
并非 const
和类似。问题是。这些设施是为了帮助你减少错误和写出更干净的代码。如果你努力地去规避这些功能,你会设法做到这一点(有时甚至不调用UB)。然而,这 "证明 "不了什么,只能证明你有可能给自己的脚打上一枪。C++不是Java,它不会牵着你的手,试图阻止你犯任何可能的错误。在这方面,C++更接近于Pythons的 "我们都是成年人"。
const被提供给:1.注释该值不应该被改变2.让编译器优化代码。允许编译器因为不应该被改变而更好地优化代码。
你不必跳过这些圈子,你可以直接使用'const_cast'来改变const'ness。
编译器 "帮助 "你强制执行const'ness,但正如你所展示的,有很多方法可以绕过它。如果你将改变一个const值将产生UB。
其原因是 行不通 (除了UB和编译器可能会优化代码外,知道了 x
是 const
)可能是因为 int y
的地址,不能持有 x
如果你运行在64位系统上。该地址很可能是一个64位的地址,其中一个最上面的32位被设置 - 而你的 int
很可能是32位。
使用正确的类型来存储地址,并让 x
volatile const
你仍然会有UB--但它可能只是。工作 如你所愿。
#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;
}