C/C++中const的区别

直入正题。
C中最初并没有const关键字,是在C++添加const后,C语言委员会的那帮人才将const加入C语言中的。
虽然加入了const,但C++与C语言中的const却有着很大不同。
我先列举const在C、C++中的关键点。
C语言中:
1.const是只读变量
2.const一定会被分配内存
3.const默认是外部链接
C++中:
1.const是只读变量
2.const不一定会被分配内存空间
3.const默认为内部链接
第一点没有什么好解释的,但有一点值得说:那就是全局const常量、局部const常量。
在C++的const被分配内存的情况下,全局const常量都存储在只读数据段,局部const常量都存储在堆栈区;
全局const常量不能被修改,局部const常量能够通过指针间接修改其值。
修改方式如下:
int main()
{
const int num = 10;
int *pNum = #
printf(“num is %d\n”,num );
*pNum = 100;
printf(“num is %d, *pNum is %d\n”,num,*pNum);
return 0;
}
以上代码运行结果会发现,通过pNum改变了num的值,这是因为num存储在堆栈区,是可以间接修改的。
若将const int num = 10;放在全局,如下:
const int num = 10;
int main()
{
int *pNum = #
printf(“num is %d\n”,num );
*pNum = 100;
printf(“num is %d, *pNum is %d\n”,num,*pNum);
return 0;
}
这段代码在编译阶段是会通过编译器语法检查的,
但是,在运行阶段,代码将崩掉,因为num在编译的时候是被做了不能修改的标志的。
大家知道,内存中并不存在数据类型,数据类型只是语言指定的规则,并在编译时中根据编译器的翻译,
转化成机器码结合CPU指令加以执行。而全局const常量在编译的时候就是因为被分配存储到只读数据区段,
该区是受到保护的区域,不容许修改其值,所以,归根结底,全部都是内存分区的缘故。
(内存各区的详情将后面的文章中总结)
现在说const在C++中何时被分配空间。
1.对const常量取地址
2.外部文件使用当前文件中的const常量
要说C++中为const常量分配地址的情况,就要了解C++为什么有时候不为它分配内存。
不被分配空间,这在C++中常量折叠或常量替换,说白了就是编译器做的优化。
如下:
int main()
{
const int num = 10;
int *pNum = #
printf(“num is %d\n”,num );
*pNum = 100;
printf(“num is %d, *pNum is %d\n”,num,*pNum);
return 0;
}
假如你在讨论第一点时运行了上面的代码时,你会发现:num的值输出为 10,*pNum输出为 100。
这表明:num内存中的数据确实被我们更改了,但num的输出值还是 10,这就是“常量折叠”,即编译器在
编译printf(“num is %d, *pNum is %d\n”,num,*pNum);这行代码时,编译器认为该const常量不会改变,
直接将num的值10编译到了printf语句中(按照编译器的角度考虑,你并没有任何征兆告诉了你要改变它,
使用 volatile关键字可以显示告诉编译器不做优化,如:volatile const int a = 10;)。

接下来,就很好理解为什么要为const常量分配内存的情况了。
对const常量取地址时,很明显,都取地址了你还不给分配地址,那就怎么玩,不分配整不了啊。
作为extern常量时,外部文件(其他编译单元,C++是以每个文件作为编译单元独立编译的,这一点很重要)
要使用该const常量,编译时分文件编译,外部文件在编译的时候,必须在编译好的程序中能够
寻址到该const常量啊,不然要怎样?所以,含有const常量的文件必须为const常量分配内存空间。
示例如下:
对const取地址
int main()
{
const int num = 10;
int pNum = (int)#
printf(“num is %d\n”,num );
*pNum = 100;
printf(“num is %d, *pNum is %d\n”,num,*pNum);
return 0;
}
下面这种情况也是分配内存的:
int main()
{
int a = 10;
const int num = a; //很明显,num的值来自变量,在运行时才得其值,运行时需要空间存储得到的 a 的值
printf(“num is %d\n”,num );
return 0;
}
extern 修饰:
file1.cpp中有一const常量
extern const int num = 30;

file2.cpp 中代码:
int main()
{
extern const int num;
printf(“num is %d\n”,num );
return 0;
}
第三点就是C与C++中const常量分文件使用的问题了。
const常量在C中默认是外部链接,C++中默认是内部链接(C++中其他的变量类型默认为外部链接)。
代码如下:
C语言中
file1.c中有一const常量
const int num = 30;

file2.cpp 中代码:
int main()
{
extern const int num;
printf(“num is %d\n”,num );
return 0;
}
C++中
file1.cpp中有一const常量
extern const int num = 30;

file2.cpp 中代码:
int main()
{
extern const int num;
printf(“num is %d\n”,num );
return 0;
}
另外补充一点:
const 与 define的区别:
1.const 有类型,define宏定义没有类型,有了类型编译器可以帮助做些检查。
2.const有作用域,define没有作用域(从定义处到文件尾),这样就无法控制变量的范围。
3.const是在编译阶段做准备工作,define宏定义则是在预编译时展开。
4.在出现bug时,若const int a = 1024引起bug,程序会报有关变量a的错误,
但是#define a 1024只会报1024引发错误(这怎么调你说)。
总结:
const修饰的变量,其目的就是防止程序员误改了变量的值,写程序时使用了const常量的初衷就是这样。
所以,定义了const变量就不要去修改它了。
const常用于修饰函数参数,指明为输入参数类型、函数返回值、修饰指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值