当我使用 *(int*)&x 赋值给常量值 x 时会发生什么?
What happens when I use *(int*)&x to assign to a constant value x?
我尝试了以下代码:
#include <iostream>
using namespace std;
struct MyClass {
const int x;
};
int main() {
MyClass c = {3};
const int *p = &c.x;
cout << "x = " << c.x << endl;
cout << "&x = " << &c.x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&c.x) << endl;
cout << endl;
*(int*)&c.x = 4;
cout << "x = " << c.x << endl;
cout << "&x = " << &c.x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&c.x) << endl;
cout << (p == &c.x) << endl;
cout << (*p == *(&c.x)) << endl;
return 0;
}
然后我得到以下答案:
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 3
*(&x) = 3
x = 4
&x = 0x61fe98
p = 0x61fe98
*p = 4
*(&x) = 4
1
1
看来我已经成功更改了常量整数 x 的值。但是当我直接在main()中而不是在类中声明x时,我得到了完全不同的答案。
#include <iostream>
using namespace std;
int main() {
const int x = 3;
const int *p = &x;
cout << "x = " << x << endl;
cout << "&x = " << &x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&x) << endl;
cout << endl;
*(int*)&x = 4;
cout << "x = " << x << endl;
cout << "&x = " << &x << endl;
cout << "p = " << p << endl;
cout << "*p = " << *p << endl;
cout << "*(&x) = " << *(&x) << endl;
cout << endl;
cout << (p == &x) << endl;
cout << (*p == *(&x)) << endl;
return 0;
}
结果是
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 3
*(&x) = 3
x = 3
&x = 0x61fe98
p = 0x61fe98
*p = 4
*(&x) = 3
1
0
这真的很奇怪,(p == &x)是真的,但(*p == *(&x))是假的!!我不知道第二个代码是怎么回事。
你正在做的事情是未定义的行为,所以任何事情都可能发生。C++标准说:
除了可以修改声明
mutable
(10.1.1) 的任何类成员之外,任何在const
对象的生存期内修改其生存期 (6.8) 的尝试都会导致未定义的行为。
和:
[注意:根据对象的类型,通过指针、左值或指向数据成员的指针的写入操作,由丢弃常量限定符的
const_cast
产生未定义的 行为 (10.1.7.1)。— 尾注]
因此,您可以丢弃"const"来获取int*
但尝试通过该指针实际修改变量是未定义的。
您可以丢弃const
的原因是它实际上可能并不指向常量:
int i = 0;
const int* p = &i;
*(int*)p = 1; // OK, because p points to a non-constant
const int j = 0;
const int* q = &j;
*(int*)q = 1; // NOT OK, because q points to a constant
在第二个示例中,编译器在优化时做出假设,基于它知道常量值不会更改的事实,因此它不会费心测试其值。这个假设是正确的,因为正确的程序永远不会改变常量的值。您的程序不正确,但这意味着编译器不需要给出合理的结果。
相关文章:
- #定义c-预处理器常量..我做错了什么
- 什么时候在C++中返回常量引用是个好主意
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- C 中的常量限定符和 C++ 中的常量限定符有什么区别?
- 常量公共成员有什么问题?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 什么时候可以使用常量装饰调用我的重载函数?
- 使用什么代替"静态常量 TCHAR *"
- 常量字符*的性质是什么?
- 初始化不是整数的巨大常量多维数组的最佳方法是什么?
- 第二个常量在运算符函数中做什么?
- 常量成员和没有setter的私有成员之间有什么区别
- 什么是常量指针常量引用类型的参数?(const X* const & p)
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 从模块导出全局常量的正确方法是什么?
- 有没有办法声明一个公共静态常量,该常量将使用 constexpr 在源文件中定义(有什么区别)?
- 有什么区别 - 常量 int x = 5000;和常量整数 x = 50'00;在C++?
- 出于什么原因,有必要将常量左值引用绑定到右值?
- 什么是可变常量?