C、C++ const对比



先从一段代码说起:

int main()
{
	int *p;
	int const a = 10;
	p = (int *)&a;
	*p = 20;

	printf("a = %d\n", a);
	printf("*p = %d\n", *p);
	printf("the address of a: %p\n", &a);
	printf("the address of p: %p\n", p);

	getchar();
	return 0;
}

如果放在C中运行(.c文件),结果为:

a = 20
*p = 20
the address of a: 000000A03DDAF7E4
the address of p: 000000A03DDAF7E4

如果放在C++中运行(.cpp文件),结果为:

a = 10
*p = 20
the address of a: 0000004E93EFFAD4
the address of p: 0000004E93EFFAD4



如果你细心观察,肯定会问:为什么在C++中,指针p与a表示同一块内存,竟然内存中的值不一样?

原因如下:

一 c语言中的常量不能直接修改,但是能通过指针访问间接修改。

C语言中会为const常量单独分配内存,只要修改了内存中的空间,就会影响常量本身。

二 C++中,const表示一个真正的常量。

C++中在const修饰的常量编译期间,值就已经确定下来了。

 const int len = 10; intarr[len];	//在C++中能编译通过,C语言中编译出错

C++编译器对const做了加强,当C++编译器扫描到const常量声明时,它不会像C语言一样为直接为const单独分配内存。 定义int const a = 10;之后,C++编译器会将a放到一个符号表里面,符号表的存在形式为key-value的形式。我们定义常量a=10,key就是a,value就是10。这个值就是锁死了,不能变的。 const变量在预处理时处理,编译器只对其值读取一次。 用到a的时候,编译器根本不会去进行内存空间的读取,会从符号表里面把a的值拿出来。

这就是C++的 常量折叠(constant folding) ,即将const常量放在符号表中,而并不给其分配内存。编译器直接进行替换优化。除非需要用到a的存储空间的时候,编译器迫不得已才会分配一个空间给a,但之后a的值仍旧从符号表中读取,不管a的存储空间中的值如何变化,都不会对常量a产生影响。但是在C语言中却不是这样,C没有constantfolding的概念。 用const定义一个常量的时候,编译器会直接开辟一个内存空间存放该常量,不会进行优化。

当然,你如果在C++中不想要这种编译优化,想让读取a的值的时候,不从符号表中去读取,而是从内存中去取。 可以用这样的定义方法:

 const volatile int  a = 10;

此时,上面代码的输出结果就会成为:

 a = 20
 *p = 20
 the address of a: 0000004E93EFFAD4 
 the address of p: 0000004E93EFFAD4

当使用&操作符取局部const常量的地址时,会分配临时的内存空间,存储在堆栈中,可通过指针修改临时空间的值;所以,编译器会为a单独的开辟一块内存空间,p = (int )&a;然后这个内存空间赋给指针p,就是p指向这个内存空间。通过p去间接修改的值,是这个新开辟的内存空间的值,而不是符号表中a的值,我们让*p=20、30、100…修改的都是新开辟内存空间中的值。不会影响到常量本身的值。

但是当const常量为全局常量时,会在全局数据区分配内存,这样的语义会产生未定义行为:

#include <iostream>
const int g = 10;
int main()
{
	int* p = (int *)&g;
	*p = 20; //段错误
	std::cout << "test\n";
	getchar();
	return 0;
}



const 和 #define 的对比

C++中的const常量与宏定义不同:
  const常量是由编译器处理的,提供类型检查和作用域检查;
  宏定义由预处理器处理,单纯的文本替换。

参考:
https://blog.csdn.net/zz460833359/article/details/48917217
https://www.cnblogs.com/WindSun/p/10207934.html
https://mp.weixin.qq.com/s/CE39RrsPhns9Ri-E9ODv2g

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值