C++深度解析 进化后的const分析---const常量,只读变量,符号表,宏定义(2)

C++深度解析 进化后的const分析(2)

 

 

 

C语言中的const变量

C语言中的const变量是只读变量,其本质还是变量,会在栈上分配空间。(通过枚举enum定义真正的常量

由于const局部变量会存放在里,而const全局变量会存在只读存储内存上。

所以我们可以通过指针来修改const局部变量,但是修改const全局变量,会使程序崩溃

示例程序一:(用gcc编译器编译)

下面程序中c不是真正意义上的常量,而是只读变量,可以通过指针来修改const局部变量。

//*.c文件
#include <stdio.h>

int main()
{
	const int c = 0;	//得到的不是真正意义上的常量,而是只读变量
	
	int* p = (int *)&c;	//通过指针修改const变量
	*p = 5;

	printf("c = %d\n", c);
	
	printf("*p = %d\n", *p);
	
	return 0;
}

结果如下:

示例程序二:(用g++编译器编译)

//*.cpp文件
#include <stdio.h>

int main()
{
	const int c = 0;	//得到的不是真正意义上的常量,而是只读变量
	
	int* p = (int *)&c;	//通过指针修改const变量
	*p = 5;

	printf("c = %d\n", c);
	
	printf("*p = %d\n", *p);
	
	return 0;
}

结果如下:

分析示例程序一和程序二,发现了什么:

通过用指针访问const修饰的只读变量c,在C语言中是可以修改的,在C++中是不可以修改的。为什么???接下来会讲到。

 

 

 

C++中的const

在C++中,当编译器在编译的过程中,碰到const修饰的标识符,将其放到符号表中。

所以编译途中遇到使用const所修饰的标识符时,则直接从符号表中将值取出来。

C++兼容C语言,会为const所修饰标识符分配空间

只要当const所修饰的标识符使用extern声明,或者被使用&操作符对const常量取地址,才会被分配存储空间

PS:C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值。(为了兼容C语言)

示例代码:

#include <stdio.h>

int main()
{
	const int c = 0;	//const局部变量
	
	int* p = (int *)&c; //使用&操作符,会分配空间
	*p = 5;

	printf("c = %d, p=%d\n", c, *p);
	return 0;
}

结果如下:

为什么输出结果会有两个不同的值?

这是因为c是真正意义上的常量,会从符号表中取出c的值,所以c=0。并在新分配空间地址修改值为5,所以打印p=5。

总结:*p修改的只是分配出来的空间地址内容,而c还是常量。(换句话来说,为c所分配的4个字节的空间是没有作用)

 

 

 

符号表

符号表是编译器在编译过程中,所产生的一张表(编译器内部的数据结构),

所以为c分配的4字节的空间,毫无意义。只是为了兼容c语言。

//将真正意义上的常量c(标识符)放入符号表
const int c = 0;

//为标识符c分配4个字节空间,并不使用这个空间
int* p = (int *)&c;

printf("Begin...\n");

//修改的是编译器为标识符c所分配的空间
*p = 5;

//编译器会查看符号表,发现里面c,对用值是0
printf("c = %d\n", c);

printf("End...\n");

 

 

 

C++的const 和 宏定义

C++中的的const常量 类似于 宏定义

const int c = 5;   ≈≈≈≈≈≈≈≈    define c 5

C++中的const常量在与宏定义不同

const常量是由编译器处理,编译器对const常量进行类型检查作用域检查

define宏定义预处理器处理,单纯的文本替换,不会进行各种检查

(预处理器是执行编译器之前运行的程序,用来删减注释,宏变量转换等)

示例程序:

#include <stdio.h>

void f()
{
	//宏是被预处理器处理的,直接进行文本替换
	#define a 3     //定义宏
	const int b = 4;//定义局部变量
}

void g()
{
	printf("a = %d\n", a);	//a=3
	//printf("b = %d\n", b);	//b的作用域f(),在f之外是不能访问b
}

int main()
{
        //A和B是真正意义上的常量
	const int A = 1;
	const int B = 2;
	//从符号表中取出数值
	int array [A + B] = {0}; //A和B是常量,从符号表取值替换,array [1 + 2]
	int i = 0;

	for(i = 0; i < (A+B); i++)
	{
		printf("array[%d] = %d\n", i, array[i]);
	}

	f();
	g();

	return 0;
}

分析上面程序:

因为执行预处理器时,会将预见到的所有a变为3,所以编译器看到的是printf("a = %d", 3);

而取消//printf("b = %d\n", b);屏蔽后,程序则会报错,是因为b的作用域只在f()函数里有效。

 

 

 

小结:

C++中的const是一个真正意义上的常量

C++编译器可能会为const常量分配空间

C++完全兼容C语言中const常量的语法特性

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值