当前位置:首页 > > 混说Linux
[导读]其实在 c++语言里面const修饰的才算是一个真正的常量,在 c 语言中 const 可以说是个“冒牌货”。为什么会这样?其实是 c++ 编译器对 const 进行了加强,当 c++ 编译器遇到常量声明时,不会像 c 语言一样给这样const对象单独分配内存,c 语言一般是放在只读数据区,而 c ++ 编译器是把const对象放在一个符号表里面(我个人觉得放在符号表里面的其中一个原因可能是想减少一些存储操作次数),至于符号表是属于内存布局(文章:你该知道你写的程序的内存布局)中的哪一块,我也不知道,写 c++ 编译器的人才知道。

const是限定一个变量不允许改变(只读),使用const在一定程度上可以提高程序的安全性和可靠性。


// 我们先来看看const的基础知识void main(){ const int a; int const b; // 和前面一个意思一样,代表常整型数 const int *c; int const *d; // 和前面一个意思一样,表示所指向的内存数据不能被修改,但是本身可以修改 int * const e; // 指针变量不能指向其他的地址,但是它所指向内存数据可以被修改 const int * const f; // 指针变量不能指向其他的地址,它所指向内存数据也不可以被修改}


我们来做一个关于const的实验:

void main(){ const int a = 10; a = 11;}// 编译报错:error: assignment of read-only variable ‘a’


从上面代码看来const好像确实是限定一个变量不允许改变(只读),定义的变量 a 貌似变成了一个常量一样,那我们接下来继续:


void main(){ // 貌似定义的 a 是一个常量 const int a = 10; // a = 11; int *p = (int *)&a; *p = 11; // 通过指针间接赋值试试看 printf("a = %d \n", a); }// 编译成功   打印结果 a = 11 


我们发现貌似定义的 a是一个常量,但是通过指针却可以间接的修改 a 的值,const不是限定变量不允许修改吗?怎么被改了?这样看来C语言中const好像确实是一个“冒牌货”。


那么同样的代码,我们看看在C++中的表现:

void main(){ // 貌似定义的 a 是一个常量 const int a = 10; // a = 11; int *p = (int *)&a; *p = 11; // 间接赋值 printf("a = %d \n", a);   system("pause");}// 打印结果 a = 10  (结果不应该是 a = 11  ?????????)// 大家可以尝试 C 和 C++ 都进行编译对比一下。


为什么 c 和 c++ 编译的结果大相径庭?好好想想,如果是你用 c++写了一个这样的程序是用在银行后台算账的,那就麻烦大了,竟然存在这样的bug?银行每天流水那么多,账要是错了,想想都害怕吧。


其实在 c++语言里面const修饰的才算是一个真正的常量,在 c 语言中 const 可以说是个“冒牌货”。为什么会这样?其实是 c++ 编译器对 const 进行了加强,当 c++ 编译器遇到常量声明时,不会像 c 语言一样给这样const对象单独分配内存,c 语言一般是放在只读数据区,而 c ++ 编译器是把const对象放在一个符号表里面(我个人觉得放在符号表里面的其中一个原因可能是想减少一些存储操作次数),至于符号表是属于内存布局(文章:你该知道你写的程序的内存布局)中的哪一块,我也不知道,写 c++ 编译器的人才知道。


在 c++ 中使用 const 对象(比如打印这个对象)的时候,就会从符号表里面把对象的值拿出来使用,比如printf("a = %d \n", a);  ,这时候就是把 a 的值10拿出来使用,但是当你对 a 取地址(&a)的时候,c++ 编译器会为这个a单独分配一个内存空间,如果定义一个指针指向这个内存空间(int *p = (int *)&a;),那么这个指针指向的是这个新分配的一个内存空间,然后通过这个指针间接修改这个值(*p = 11;),这时候修改的其实新分配的这个空间的值,不管你间接修改的这个值是11、20、30还是100,都和符号表原本的 a 的值没有任何关系,所以使用 a 的时候打印出来的结果是 a = 10,这就是符号表,是 c++ 对 c 的一些扩展,这样就会发现 c++ 编译器把 const 变成符号表这个手段确确实实把 const 修饰的变量变成了一个常量,结论就是在 c 语言里面 const 确实是一个“冒牌货”。


这时候可能还有一个疑问,这个新分配的内存到底存不存在?这个简单,我们加一句打印就行:

void main(){ // 貌似定义的 a 是一个常量 const int a = 10; // a = 11; int *p = (int *)&a; *p = 11; // 间接赋值  printf("*p = %d \n", *p); // 加上这句打印 printf(" a = %d \n", a);   system("pause");}// 打印结果:*p = 11     a = 10


从打印可以看出单独分配的这个内存空间值是11,和原来的 a 是不同的两个概念,这就是在 C++ 中 const 的符号表的实现机制。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭