真的很不想讲这个,但是有些人就是死脑筋一样,我今天就讲一个UB的情况
#include<iostream>
int main()
{
const int num = 1;
int* p_num = (int*)#
*p_num = 2;
int a = num, b = *p_num;
std::cout << num << std::endl;
std::cout << a << std::endl;
std::cout << b << std::endl;
}
这是一段非常简单的代码,运行结果如下:
这是一种UB,那么为什么是这种结果。看下面
听好了,再听不懂真别学了。这是在MSVC编译器的环境下,首先明确一个概念,C++内const修饰表示常量,在编译器看来这块内存就像被标记了一样,永远,是永远无法被改变,这是常量,不要抠字眼,在ISO委员会的标准中是如此。那么修改分为直接修改和间接修改。
1、直接修改,没什么好说的直接error退出程序,非法行为
2、间接修改,编译器会对这种行为做优化,编译器会无视你对常量间接修改的操作,也不会中断报错,这个时候看图,指针指向了常量的num,解引用就是1,这个注意看上面内存&p_num,此时的指针地址,第二图指针的地址,发现了吗,指针的地址变了,或许不该这么说,这是指针自身的地址,它变了表示着,此指针非彼指针,编译器的优化是,既然你想要给常量赋值2,修改它,我肯定是不允许的,但是我可以让你满足你的指针指向的是2,编译器直接替换了一个新的指针,这也是为什么指针自身的地址变了,表示着这是编译器开辟了一块内存,内存的值是2,把这块内存的地址作为了p_num,所以最好常量还是1,b被赋值为*p_num也就是地址*取值为2,,b变成了2.
最后说一句,这个东西动点脑子就看的出来,了解这些编译器的具体行为其实未必重要。