通过非常量指针修改常量
我对以下代码中发生的事情有点困惑:
const int e = 2;
int* w = ( int* ) &e; // (1) cast to remove const-ness
*w = 5; // (2)
cout << *w << endl; // (3) outputs 5
cout << e << endl; // (4) outputs 2
cout << "w = " << w << endl; // (5) w points to the address of e
cout << "&e = " << &e << endl;
在(1)中,w指向e的地址。在(2)中,该值改为5。但是,当显示*w和e的值时,它们的值是不同的。但是如果你打印 w 指针和 &e 的值,它们具有相同的值/地址。
为什么 e 变成了 5 还是 2?它们是否存储在单独的位置?还是临时的?但为什么w指向的值仍然是e的地址呢?
I'm a bit confused what happened in the following code:
const int e = 2;
int* w = ( int* ) &e; // (1) cast to remove const-ness
*w = 5; // (2)
cout << *w << endl; // (3) outputs 5
cout << e << endl; // (4) outputs 2
cout << "w = " << w << endl; // (5) w points to the address of e
cout << "&e = " << &e << endl;
In (1), w points to the address of e. In (2), that value was changed to 5. However, when the values of *w and e were displayed, their values are different. But if you print value of w pointer and &e, they have the same value/address.
How come e still contained 2, even if it was changed to 5? Were they stored in a separate location? Or a temporary? But how come the value pointed by w is still the address of e?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
正如我在评论中所说,一旦你修改了 const 值,你就处于未定义的行为领域,所以谈论正在发生的事情没有多大意义。但到底是什么......
猜测,
*w
正在运行时评估,但e
被视为编译时常量As I said in my comment, once you modified the const value you are in undefined behaviour land, so it doesn't make much sense to talk about what is happening. But what the hell..
At a guess,
*w
is being evaluated at runtime, bute
is being treated as a compile time constant我怀疑你让编译器出错了。它不希望您对 e 玩弄肮脏的把戏,因此当它看到以下行时:
它只是插入值 2 而不是查找实际值。您可以通过查看程序的反汇编来验证(或反驳)这一点。
I suspect that you're tripping up the compiler. It doesn't expect you to play dirty tricks with e, so when it sees the line:
It simply inserts the value 2 instead of looking for the actual value. You can verify (or disprove) this by looking at the disassembly of your program.
我猜测编译器已经优化了值输出。它发现
e
是 const(因此,理论上它不能改变)并更改cout << e << endl;
到cout << 2<<;结束;
。但是,e
仍然必须存在,因为它被w
使用,因此w
正确地获取其地址并修改其值,但您不这样做请参阅cout
中的内容。这个故事的寓意是——仅当您确实想要成为
const
时才声明事物const
。抛弃常量并不是一个好主意。I'm guessing that the compiler has optimised the value output. It sees that
e
is const (so, it can't change -- in theory) and changescout << e << endl;
tocout << 2 << endl;
. However,e
still has to exist because it's used byw
, sow
correctly takes its address and modifies its value, but you don't see that in thecout
.Moral of the story -- only declare things
const
when you actually want to beconst
. Casting awayconst
ness is not a good idea.我唯一能想到的是编译器对代码进行了一些优化,即使它为 e 分配了内存,但对 e 的任何引用都被替换为值 2,
因此实际上(影响?)注释行(4) 被“优化”为
The only thing I can think of is the compiler has some how optimised the code in such a way that any references to e are replaced with a value of 2 even though it assigns memory for e
so in effect (affect?) the line at comment (4) is 'optimized' to be
我猜编译器使用常量来优化变量并将固定值插入代码中。
I guess the compiler uses the constness to optimizes out the variable and insert a fixed value into the code.
C++14 标准的 [dcl.type.cv]/4 节涵盖了这一点(早期标准也有类似的文本):
e
是一个 const 对象,并且*w = 5;
尝试修改该对象,因此结果是 未定义的行为。This is covered by section [dcl.type.cv]/4 of the C++14 standard (earlier standards had similar text too):
e
is a const object, and*w = 5;
attempts to modify that object, therefore the result is undefined behavior.