1

可能重复:
通过非常量指针修改 const

我正在学习 C++,并且对指针非常感兴趣。我试图改变一个常数值的值(我的老师称之为backdoor,如果我错了,请澄清),如下所示:

const int i = 0;

const int* pi = &i;

int hackingAddress = (int)pi;
int *hackingPointer = (int*)pi;

*hackingPointer = 1;

cout << "Address:\t" << &i << "\t" << hackingPointer << endl;
cout << "Value:  \t" << i << "\t\t" << *hackingPointer << endl;

system("PAUSE");

return 0;

然而,结果很奇怪。虽然这两个地址相同,但值不同。

我的代码是如何执行的?而价值究竟存储0在哪里?1

4

3 回答 3

11

您发现了一个 C++ 开发人员称之为未定义行为的小东西。您告诉编译器“i是一个值为 0 的常量”。因此,当您向编译器询问 的值时i,它会告诉您它是 0。

试图更改常量的值违反了编译器所做的假设(常量将是常量),因此编译器将生成无效或不一致的代码。

在 C++ 中有很多情况,可以在编译器不将其捕获为错误的情况下执行某些操作,但结果是undefined。如果你这样做,那么你会得到你所看到的结果。编译器做了一些奇怪和意想不到的事情。

哦,如果你的老师试图通过这样的例子教你任何东西,他就错了,你应该非常害怕。

您从这样的代码中获得的唯一保证是:

编译器可以做任何它喜欢的事情

当您编写代码时,您与编译器有一个隐式契约:

“如果我编写了定义明确的 C++ 代码,那么您将其转换为具有与 C++ 标准描述的相同效果的可执行文件”。

当你做这样的事情时,你就违反了合同。然后编译器也没有义务遵循它。如果您提供的编译器代码没有根据 C++ 标准明确定义,那么它就不能也不会创建一个按照 C++ 标准指定的可执行文件。

于 2012-05-29T10:47:53.183 回答
2

看来,编译器已经优化(内联 int const 值)

cout << "Value:  \t" << i << "\t\t" << *hackingPointer << endl;

cout << "Value:  \t" << 0 << "\t\t" << *(0x0044ff28) << endl;

无论如何,您仍然成功地更改了存储位置的内存值i。但是不要在家里尝试这个:-)

于 2012-05-29T10:53:46.087 回答
0

不允许更改常量的值,实际上这是未定义的行为,因此您的程序可以做任何事情

在这种情况下,您的编译器似乎在编译时优化了读取,因为它知道值是固定的。当您尝试更改它时,许多实现可能会崩溃,但您不能也不应该赌注或依赖任何未定义行为的结果。

于 2012-05-29T10:49:18.853 回答