我很好奇为什么我的研究结果很奇怪
#include <iostream>
int test()
{
return 0;
}
int main()
{
/*include either the next line or the one after*/
const int a = test(); //the result is 1:1
const int a = 0; //the result is 0:1
int* ra = (int*)((void*)&a);
*ra = 1;
std::cout << a << ":" << *ra << std::endl;
return 0;
}
为什么常量 var 在运行时初始化可以完全更改,但在编译时初始化只会更改指针的 var?
该函数在这里并不那么相关。原则上,您可以为此代码获得相同的输出 (0:1(:
int main() {
const int a = 0;
int* ra = (int*)((void*)&a);
*ra = 1;
std::cout << a << ":" << *ra;
}
a
是const int
而不是int
。您可以执行各种无意义的 c 转换,但修改const
对象会调用未定义的行为。
顺便说一下,在上面的示例中,即使对于std::cout << a << ":" << a;
编译器,也允许编译器发出打印1:0
(或42:3.1415927
(的代码。当你的代码有未找到的行为时,任何事情都可能发生。
PS:如果你想研究编译器的内部结构以及它对不是有效 C++ 代码的代码的作用,函数和不同的结果是相关的。为此,最好查看编译器的输出以及它在两种情况下的不同之处(https://godbolt.org/(。
强制转换const
变量并更改其值是未定义的行为。如果你尝试,任何事情都可能发生。
无论如何,似乎发生的事情是编译器看到const int a = 0;
,并根据优化将其放在堆栈上,但将所有用法替换为 0(因为a
不会改变!对于*ra = 1;
,存储在内存中的值实际上会发生变化(堆栈是读写的(,并输出该值。
对于const int a = test();
,依赖于优化,程序实际上调用函数test()
并将值放在堆栈上,在那里它被*ra = 1
修改,这也改变了一个。