c++/c常量

2021-12-07 1449

1.字面常量

字面常量是在程序中使用的最多的常量,例如,直接出现的各种进制的数字、字符(‘’括住的单个字符)或字符串(“”括住的一系列字符)等。实际上,只存在基本数据类型的字面常量。下边是一些字面常量的例子

c++/c常量

由于字面常量只能引用,不能修改,所以语言实现一般把它保存在程序的符号表里,而不是一般的数据区。符号表是“只读”的,其实它是一种访问保护机制,千万不要理解为只读存储器(ROM)。除了字符串外,你无法读取一个字面常量的地址。
例如:
int*p=&5;这类语句是错误的。
当你试图通过字符常量字符串的地址修改其中的字符时,就会报告“只读”错误。例如:
*(pChar+2)=’k’; //错误,不能修改字面常量的内存单元

如果程序中到处都充斥着各种各样的字面常量,那么就可能存在相同的常量,我们应该把相同的常量合并,以减少内存消耗。有些连接器自动执行常量合并,而有些连接器则是提供了常量合并的开关,以优化程序的效率。如果你的编译链接环境支持常量合并,请将它打开。

2.符号常量

存在两种符号常量:一是用#define定义的宏常量,二是用const定义的常量。
由于#define是预编译伪指令,它定义的宏常量在进入编译阶段前就已经被替换为所代表的字面常量了。因此,宏变量在本质上是字面常量。
在c语言中,用const定义的常量,其实是值不能修改的变量,因此会给它分配存储空间(外连接的)
但是在c++中,const定义的常量要具体情况具体对待:对于基本数据类型的常量,编译器会把它放到符号表中,而不分配存储空间,而ADT/UDT的const对象则需要分配存储空间(大对象)。
还有一些情况也需要分配存储空间,例如:强制声明为extern 的符号常量,或取符号常量的地址等操作的时候,都会强迫编译器为这些常量分配存储空间,以满足用户的需求。

我们可以取一个const符号常量的地址:对于基本数据类型的const常量,编译器会在内存中创建一个它的拷贝,我们通过其地址访问到的就是这个拷贝,而非原始的符号常量,而对于构造类型的const常量,实际上它是编译时不允许修改的变量,因此,如果我们能绕过编译器的静态类型的安全检查机制,就可以在运行时修改其内存单元。
c++/c常量

这个例子说明,const符号只是编译时(源代码级,或者语言层面)强类型安全检查机制的一种手段,以帮助程序员发现无意中要修改他们的代码并进行修正,而在运行时(二进制层面)无法阻止恶意的修改。

提醒:
从理论上讲,只要你手中握有一个对象的指针(内存地址),你就可以设法绕过编译器随意修改它的内容,除非该内存受到操作系统的保护。也就是说,c++并没有提供对指针有效性的静态检查,而是把它丢给了操作系统,这正是使用指针危险的地方所在。

在标准c语言中,const符号常量默认的是外连接的(分配存储),也就是说你不能在两个(或两个以上)的编译单元中同时定义一个同名的const符号常量(重定义错误),或者把一个const符号常量定义放在一个头文件中,而在多个编译单元中同时包含该头文件。

但是在标准c++中,const符号常量默认是内连接的,因此可以定义在头文件中。当在不同的编译单元中同时包含该头文件时,编译器认为他们是不同的符号常量,因此每个编译单元独立编译时会分别为他们分配存储空间,而在连接时进行常量合并。

以上就是c++/c常量的详细内容,更多请关注php知识-学习天地 www.lxywzjs.com其它相关文章!

分享至:

分享到QQ空间 分享到朋友社区 新浪微博分享

栏目地图