文章目录
1 C语言中的const只读变量
1.1 const只读变量的特性
对于const只读变量我们需要知道:
- const修饰的变量是只读的,本质还是变量。
- const修饰的局部变量在栈上分配空间。
- const修饰的全局变量在全局数据区分配空间。
- const只在编译器有用,在运行期无用。
const修饰的变量不是真的常量,const只是使得变量具有只读属性,它只是告诉编译器该变量不能出现在赋值符号的左边。因此,const不能定义真正意义上的常量。
1.2 const全局变量的分歧
在现代C语言编译器中的const将具有全局生命周期的变量(全局变量、静态局部变量)存储于只读存储区,修改const全局变量将导致程序崩溃。
注意: 标准C语言编译器不会将const修饰的全局变量存储于只读存储区,而是存储于可修改的全局数据区,其值依然可以改变。

示例代码如下:
#include <stdio.h>
const int g_array[5] = {0};
void modify(int* p, int v)
{
*p = v;
}
int main()
{
int const i = 0;
const static int j = 0;
int const array[5] = {0};
modify((int*)&i, 1); // ok
modify((int*)&j, 2); // error
modify((int*)&array[0], 3); // ok
modify((int*)&g_array[0], 4); // error
printf("i = %d\n", i);
printf("j = %d\n", j);
printf("array[0] = %d\n", array[0]);
printf("g_array[0] = %d\n", g_array[0]);
return 0;
}
2 const修饰函数参数和返回值
2.1 const修饰函数参数和返回值
对于const修饰函数参数和返回值:
- const修饰函数参数表示在函数体内不希望改变参数的值。
- const修饰函数返回值表示返回值不可改变,多用于返回指针的情形。
另外,C语言中的字符串字面量存储于只读存储区中,在程序中需要使用const char*指针。

3 C++中的const
3.1 C++中的cosnt
C++在C的基础上对const进行了处理:
- 当碰见const声明时在符号表中放入常量;
- 编译过程若发现使用常量则直接以符号表中的值替换;
编译过程中若发现下述情况则给对应的常量分配存储空间:
- 对const常量使用了extern。
- 对const常量使用了& 操作符。
注意:C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值。

C++中的int类型的const常量在数组定义时可以直接作为数组的大小。
3.2 C和C++中const变量的区别
C语言中的const常量:
- C语言中的const变量是只读变量,会分配存储空间。
C++中的const常量:
- 可能会分配存储空间:当const常量为全局变量,并且需要在其他文件中使用,当使用& 操作符对const常量取地址。
3.3 C++中const常量和宏定义的区别
C++中的const常量类似于宏定义:
- cons tint c = 5; ≈ #define c 5
C++中的const常量与宏定义不同:
- const常量是由编译器处理;
- 编译器对const常量进行类型检查和作用域检查;
- 宏定义由预处理器处理,单纯的文本替换。
3.4 C++中的const常量和const只读变量
const什么时候为只读变量?什么时候是常量?
const常量的判别准则:
- 只有用字面量初始化的const常量才会进入符号表;
- 使用其他变量初始化的const常量仍然是只读变量;
- 被volatile修饰的const常量不会进入符号表。
注意:在编译期间不能直接确定初始值的const标识符,都被作为只读变量处理。当const作用域类的成员变量时,类的成员变量也将称为只读变量。
cosnt引用的类型与初始化变量的类型:
- 相同:初始化变量成为只读变量;
- 不同:生成一个新的只读变量。
编程实验:cosnt典型问题分析
#include <stdio.h>
int main()
{
const int x = 1;
const int& rx = x;
int& nrx = const_cast<int&>(rx);
nrx = 5;
printf("x = %d\n", x);
printf("rx = %d\n", rx);
printf("nrx = %d\n", nrx);
printf("&x = %p\n", &x);
printf("&rx = %p\n", &rx);
printf("&nrx = %p\n", &nrx);
volatile const int y = 2;
int* p = const_cast<int*>(&y);
*p = 6;
printf("y = %d\n", y);
printf("p = %p\n", p);
const int z = y;
p = const_cast<int*>(&z);
*p = 7;
printf("z = %d\n", z);
printf("p = %p\n", p);
char c = 'c';
char& rc = c;
const int& trc = c;//char会默认转换为int,编译通过,生成新的只读变量
rc = 'a';
printf("c = %c\n", c);//a
printf("rc = %c\n", rc);//a
printf("trc = %c\n", trc);//c
return 0;
}
/*
x = 1
rx = 5
nrx = 5
&x = 0xbf8c849c
&rx = 0xbf8c849c
&nrx = 0xbf8c849c
y = 6
p = 0xbf8c84a0
z = 7
p = 0xbf8c84a4
c = a
rc = a
trc = c
*/
3.5 类中的const成员
类中的const成员:
- 类中的const成员会被分配空间的,和对象存储空间一起。
- 类中的const成员的本质是只读变量。
- 类中的const成员只能在初始化列表中指定初始值。
编译器无法直接得到const成员的初始值,因此无法进入符号表称为真正意义上的常量。
#include <stdio.h>
class Test
{
private:
const int ci;
public:
Test()
{
printf("Test::Test()\n");
}
int getCI()
{
return ci;
}
int setCI(int v)
{
int* p = const_cast<int*>(&ci);
*p = v;
}
};
int main()
{
Test t;
printf("t.ci = %d\n", t.getCI()); // 100
t.setCI(10);
printf("t.ci = %d\n", t.getCI()); // 10
return 0;
}
3.6 C++中的const对象
关于const对象:
- const关键字能够修饰对象。
- const修饰的对象为只读对象。
- 只读对象的成员变量不允许被改变。
- 只读对象是编译阶段的概念,运行时无效。
- const对象只能调用const成员函数。
参考资料:
本文深入探讨了C和C++中const关键字的使用,包括只读变量、全局变量的分歧、函数参数和返回值的修饰,以及C++中const的特殊处理。通过实例代码展示了const在不同场景下的行为,如修饰类成员、const对象和引用。
2641

被折叠的 条评论
为什么被折叠?



