C与C++中 const 的区别

常量与const?

什么是常量?
常量就是一个不变的量,或者说就是一个字面值,但是const指定的量不一定是一个常量。
在C语言中,const更确切来说指定的是一个只读变量。
而C++中,const只是指定向编译器寻求宏替换
(可能这句话你会有点陌生,没关系,后面会详细讲解)

那么C/C++中的const指定的量真的就一成不变吗?或者说真的就安全吗?
我们在.c文件下(c语言环境)运行以下程序:
在这里插入图片描述
(注意:需要对&a做一次强制类型转换,不然会报warning,甚至error)

输出结果:
我们发现虽然a被我们定义成了const int 变量,但只要得到了它的地址,仍然是能够修改它的值的。

同样的代码,我们在.cpp文件(C++环境)下再运行一次

在这里插入图片描述
输出结果:
在这里插入图片描述
我们可以发现,p确实得到了a的地址,但是改变*p,a却没有变化了,这是为什么?

原因:
还记得我之前那句话吗?
在C语言中,const更确切来说指定的是一个只读变量。而C++中,const只是指定向编译器寻求宏替换。
C语言中,const指定一个只读变量,其终究是一个变量,可以修改的,如何修改?就是上面测试时用的方法–访问其内存。但我们也不能忽略其只读性,也就是说,单纯访问该变量应该注意它的只读性,甚至语法要求你只能在初始化时对他进行一次值修改。

而在C++中,const只是指定向编译器寻求宏替换。宏替换是编译期进行的,替换的东西是:把所有出现const变量的地方换成一个字面值。这就可以解释在C++下运行为什么会出现不同的结果:当我们第二条输出语句输出a时,其实输出的是预编译期就确定下来的一个字面量,而*p是程序运行期才确定下来的。所以,a在内存中的值确实已经被修改了,只是我们看不到而已。

让我们看一段反汇编代码,来证实以上说法:
在这里插入图片描述
可以看到在 int b = a; 这一句下面,其执行的是直接将0Ch,也就是12直接赋值给了b,而没有去访问a内存的值。

但是:C++这样做就安全了吗?
既然C++中的const只是在编译期进行了宏替换,那如果const变量的值是在预编译期不能知道的呢?
如果你不能理解什么意思,请看以下程序。
在这里插入图片描述
输出结果:
在这里插入图片描述
可以发现a的值这次能看出来真的被改变了,其原因是:对a的初始化不再是一个预编译期能确定的值了,所以编译器没办法帮你完成宏替换了。

反汇编验证一下:
在这里插入图片描述
在 int b = a这一句下面,可以看到,这次并没有直接用字面值赋值,也就是说没有宏替换,而是dword ptr[a],访问内存中a的值给b。

更骚一点,我们可以对一个顶层指针也探究一下,毕竟指针也是一个变量。
测试代码

扫描二维码关注公众号,回复: 10263464 查看本文章

在这里插入图片描述
同样,用字面量初始化的指针,被进行了宏替换,其值看起来没有改变,但是以一个变量初始化的顶层指针,已经被改变。虽然本质上两者内存的值都已经改变。

总结:

const并不能保证一个变量始终不变,如果你不想它的值被改变,就不要访问内存去改变它。另外,C++中的指针是很灵活的,它可以被强制类型转换成任何你需要的类型,所以当你能够得到一个变量的地址时,这个变量就变得不那么安全了。

发布了8 篇原创文章 · 获赞 22 · 访问量 3314

猜你喜欢

转载自blog.csdn.net/weixin_43406295/article/details/88626707