【从 C 向 C++ 进阶】- 对 C 的语法扩展 - const 关键字

从 C 向 C++ 进阶系列导航


1. const 关键字

在 C 中,const 关键字可以改变变量的属性以及存储空间。不同的判别标准如下:

  • 修饰局部变量:变量具有只读属性,仍保存在内存的栈中,可通过指针访问地址进行修改。
  • 修饰全局变量或静态变量:变量存储空间由静态存储区改变为只读存储区(.rodate段),且不能用指针来修改。

在 C++ 中,对 const 关键字的作用进行了优化。编译器编译过程中遇到 const 修饰的标识符时,会将 const 修饰的标识符放入符号表中。如果后续编译过程中发现 const 修饰的标识符时,直接使用符号表中 const 修饰的标识符对应的值直接替换。

  • 示例:
int main(void)
{
    const int var_con = 3;
    int arr[var_con] = {0};     // 等价于 int arr[3] = {0};
}

以上在 C++ 是合法的,但在 C 中会发生编译错误,因为在 C 中只读变量不能作为左值。


2. C++ 的 const 常量

const 常量的判别标准:

  • 用字面量初始化的 const 常量会进入符号表,因为在编译期间常量值已确定。
  • 用已存在的变量初始化的 const 常量仍为只读变量,因为在编译期间常量值无法确定。
  • 被 volatile 修饰的 const 常量不会进入符号表。

C++ 想是把 const 修饰的变量从 C 中的只读变量优化为真正意义上的常量,但为了兼容 C 语言的做法,在以下情况下,编译器会给 const 常量分配空间:

  • const 常量为全局(extern修饰),并且需要在其它文件中使用。
  • 使用 & 操作符对 cosnt 常量取地址。

虽然编译器对 const 常量分配了空间,但不会使用其存储空间的值。

  • 实验
int main()
{
	int *p = NULL;
	
	/* 用字面量初始化 const 常量 */
	const int var_con_A = 2;                            // 进入符号表
	cout << "sizeof(var_con_A) = " << sizeof(var_con_A) << endl;	// 由于 sizeof 发生在预处理阶段,因此可以得到对应的内存大小
	cout << "var_con_A = " << var_con_A << endl;		// var_con_A = 2
	p = (int*)&var_con_A;
	*p = 3;
	cout << "*p = " << *p << endl;						// *p = 3
	cout << "p = " << p << endl;						// p = 0x7fff84f1a070
	cout << "var_con_A = " << var_con_A << endl;		// var_con_A = 2,编译过程中已替换
	cout << "&var_con_A = " << &var_con_A << endl;	    // &var_con_A = 0x7fff84f1a070
	int arr_A[var_con_A] = {0};		                    // no error
	
	/* 用已存在的变量初始化 const 常量 */
	int num = 5;
	const int var_con_B = num;                          // 未进入符号表
	cout << "var_con_B = " << var_con_B << endl;		// var_con_B = 5
	p = (int*)&var_con_B;
	*p = 6;
	cout << "*p = " << *p << endl;						// *p = 6
	cout << "p = " << p << endl;						// p = 0x7fff84f1a074
	cout << "var_con_B = " << var_con_B << endl;		// var_con_B = 6
	cout << "&var_con_B = " << &var_con_B << endl;	    // &var_con_B = 0x7fff84f1a074
	int arr_B[var_con_B] = {0};	                    	// no error
	
	/* volatile 修饰的 const 常量 */
	volatile const int var_con_vol = 8;                 // 未进入符号表	
	cout << "var_con_vol = " << var_con_vol << endl;	// var_con_vol = 8
	p = (int*)&var_con_vol;
	*p = 9;
	cout << "*p = " << *p << endl;						// *p = 9
	cout << "p = " << p << endl;						// p = 0x7fff84f1a078
	cout << "var_con_vol = " << var_con_vol << endl;	// var_con_vol = 9
	cout << "&var_con_vol = " << &var_con_vol << endl;	// &var_con_vol = 1	
	int arr_vol[var_con_vol] = {0};	                   	// no error	
}
发布了60 篇原创文章 · 获赞 36 · 访问量 5960

猜你喜欢

转载自blog.csdn.net/qq_35692077/article/details/95890883