C++ 同一地址的变量如何产生两个不同的值?

C++ 同一地址的变量如何产生两个不同的值?,c++,casting,constants,undefined-behavior,C++,Casting,Constants,Undefined Behavior,考虑这一点: #include <iostream> using namespace std; int main(void) { const int a1 = 40; const int* b1 = &a1; char* c1 = (char *)(b1); *c1 = 'A'; int *t = (int*)c1; cout << a1 << " " << *t << en

考虑这一点:

#include <iostream>
using namespace std;

int main(void)
{
    const int a1 = 40;
    const int* b1 = &a1;
    char* c1 = (char *)(b1);
    *c1 = 'A';
    int *t = (int*)c1;


    cout << a1 << " " << *t << endl;
    cout << &a1 << " " << t << endl; 

    return 0;
}

这对我来说几乎是不可能的,除非编译器正在进行优化。怎么做

您的代码具有未定义的行为,因为您正在修改常量对象。任何事情都有可能发生,没有什么是不可能的。

这就是说,您正在修改一个常量变量,以便对结果没有任何期望。我们可以看到,通过C++标准部分草案<代码> 7.1.61 CV限定符第4段,该段表示:

[…]在常量对象的生存期(3.8)内修改常量对象的任何尝试都会导致未定义的行为

甚至提供了一个例子:

const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
const int*ciq=新const int(3);//根据需要初始化
int*iq=const_cast(ciq);//要求演员
*智商=4;//未定义:修改常量对象
1.3.24节
中未定义行为的标准定义中,给出了以下可能的行为:

[…]允许的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特有的记录方式(有或没有发布 诊断消息),以终止转换或执行(发出诊断消息)。[……]


当您限定它们为变量
const
时,编译器可以假设一些事情并生成代码,只要您尊重这一约定而不是破坏它,这就可以很好地工作。当你打破它,你会得到未定义的行为


请注意,当删除
const
时,它会按预期工作

正如其他人所解释的,修改
const
值会导致未定义的行为,无需多说-任何结果都是可能的,包括完全无意义或崩溃


如果您对这个特定结果是如何产生的感到好奇,几乎可以肯定这是由于优化。由于您将
a
定义为
const
,编译器可以随时替换您分配给它的值
40
;毕竟,它的价值是不会改变的,对吧?例如,当您使用
a
定义数组的大小时,这非常有用。即使在gcc中(它有一个用于可变大小数组的扩展),编译器也更容易分配一个恒定大小的数组。一旦优化存在,它可能会被一致地应用。

为什么修改常量变量会导致未定义的行为?@Ben,因为规范这么说。@Ben,正如巴特所说,因为标准这么说。标准这么说的原因是1)允许编译器将变量放入只读内存(例如,您试图修改它可能会导致程序崩溃),2)允许编译器将常量值作为常量表达式传播:如果您稍后编写
char arr[a1],你希望数组有多大?@JamesKanze好的,谢谢。@ben一个常量应该是常量,如果它改变了,就不应该是常量。因此,试图这样做,在语义上是胡说八道。如果有人在运行过程中改变PI值,会发生什么?胡说八道,没有定义的行为。C++让你做非常危险的事情(这是C++的一种力量),但有时危险会导致胡说八道。如果你的问题已经得到了答案,请不要发表评论,感谢回答者。您也可以选择已接受的答案以及您认为有用的任何其他答案。谢谢。我会记住的。
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object