C语言中const竟是个“冒牌货”!

嵌入式ARM 2023-01-03 12:00

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 的符号表的实现机制。


END

作者:Linux_Daily

来源:混说Linux


版权归原作者所有,如有侵权,请联系删除。

推荐阅读
RTO‍S -> Linux" linktype="text" imgurl="" imgdata="null" data-itemshowtype="0" tab="innerlink" style="text-decoration: underline;" data-linktype="2">单片机 -> RTOS -> Linux
50条C语言奇技淫巧,精品干货!
10个超赞的C语言开源项目,强烈推荐!

→点关注,不迷路←

嵌入式ARM 关注这个时代最火的嵌入式ARM,你想知道的都在这里。
评论
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-11 17:58 83浏览
  • 铁氧体芯片是一种基于铁氧体磁性材料制成的芯片,在通信、传感器、储能等领域有着广泛的应用。铁氧体磁性材料能够通过外加磁场调控其导电性质和反射性质,因此在信号处理和传感器技术方面有着独特的优势。以下是对半导体划片机在铁氧体划切领域应用的详细阐述: 一、半导体划片机的工作原理与特点半导体划片机是一种使用刀片或通过激光等方式高精度切割被加工物的装置,是半导体后道封测中晶圆切割和WLP切割环节的关键设备。它结合了水气电、空气静压高速主轴、精密机械传动、传感器及自动化控制等先进技术,具有高精度、高
    博捷芯划片机 2024-12-12 09:16 82浏览
  • 习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习笔记&记录学习习笔记&记学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记录学习学习笔记&记
    youyeye 2024-12-12 10:13 31浏览
  • 本文介绍瑞芯微RK3588主板/开发板Android12系统下,APK签名文件生成方法。触觉智能EVB3588开发板演示,搭载了瑞芯微RK3588芯片,该开发板是核心板加底板设计,音视频接口、通信接口等各类接口一应俱全,可帮助企业提高产品开发效率,缩短上市时间,降低成本和设计风险。工具准备下载Keytool-ImportKeyPair工具在源码:build/target/product/security/系统初始签名文件目录中,将以下三个文件拷贝出来:platform.pem;platform.
    Industio_触觉智能 2024-12-12 10:27 43浏览
  • 天问Block和Mixly是两个不同的编程工具,分别在单片机开发和教育编程领域有各自的应用。以下是对它们的详细比较: 基本定义 天问Block:天问Block是一个基于区块链技术的数字身份验证和数据交换平台。它的目标是为用户提供一个安全、去中心化、可信任的数字身份验证和数据交换解决方案。 Mixly:Mixly是一款由北京师范大学教育学部创客教育实验室开发的图形化编程软件,旨在为初学者提供一个易于学习和使用的Arduino编程环境。 主要功能 天问Block:支持STC全系列8位单片机,32位
    丙丁先生 2024-12-11 13:15 63浏览
  • RK3506 是瑞芯微推出的MPU产品,芯片制程为22nm,定位于轻量级、低成本解决方案。该MPU具有低功耗、外设接口丰富、实时性高的特点,适合用多种工商业场景。本文将基于RK3506的设计特点,为大家分析其应用场景。RK3506核心板主要分为三个型号,各型号间的区别如下图:​图 1  RK3506核心板处理器型号场景1:显示HMIRK3506核心板显示接口支持RGB、MIPI、QSPI输出,且支持2D图形加速,轻松运行QT、LVGL等GUI,最快3S内开
    万象奥科 2024-12-11 15:42 86浏览
  • 一、SAE J1939协议概述SAE J1939协议是由美国汽车工程师协会(SAE,Society of Automotive Engineers)定义的一种用于重型车辆和工业设备中的通信协议,主要应用于车辆和设备之间的实时数据交换。J1939基于CAN(Controller Area Network)总线技术,使用29bit的扩展标识符和扩展数据帧,CAN通信速率为250Kbps,用于车载电子控制单元(ECU)之间的通信和控制。小北同学在之前也对J1939协议做过扫盲科普【科普系列】SAE J
    北汇信息 2024-12-11 15:45 110浏览
  • 时源芯微——RE超标整机定位与解决详细流程一、 初步测量与问题确认使用专业的电磁辐射测量设备,对整机的辐射发射进行精确测量。确认是否存在RE超标问题,并记录超标频段和幅度。二、电缆检查与处理若存在信号电缆:步骤一:拔掉所有信号电缆,仅保留电源线,再次测量整机的辐射发射。若测量合格:判定问题出在信号电缆上,可能是电缆的共模电流导致。逐一连接信号电缆,每次连接后测量,定位具体哪根电缆或接口导致超标。对问题电缆进行处理,如加共模扼流圈、滤波器,或优化电缆布局和屏蔽。重新连接所有电缆,再次测量
    时源芯微 2024-12-11 17:11 109浏览
  • 在智能化技术快速发展当下,图像数据的采集与处理逐渐成为自动驾驶、工业等领域的一项关键技术。高质量的图像数据采集与算法集成测试都是确保系统性能和可靠性的关键。随着技术的不断进步,对于图像数据的采集、处理和分析的需求日益增长,这不仅要求我们拥有高性能的相机硬件,还要求我们能够高效地集成和测试各种算法。我们探索了一种多源相机数据采集与算法集成测试方案,能够满足不同应用场景下对图像采集和算法测试的多样化需求,确保数据的准确性和算法的有效性。一、相机组成相机一般由镜头(Lens),图像传感器(Image
    康谋 2024-12-12 09:45 74浏览
  • 全球智能电视时代来临这年头若是消费者想随意地从各个通路中选购电视时,不难发现目前市场上的产品都已是具有智能联网功能的智能电视了,可以宣告智能电视的普及时代已到临!Google从2021年开始大力推广Google TV(即原Android TV的升级版),其他各大品牌商也都跟进推出搭载Google TV操作系统的机种,除了Google TV外,LG、Samsung、Panasonic等大厂牌也开发出自家的智能电视平台,可以看出各家业者都一致地看好这块大饼。智能电视的Wi-Fi连线怎么消失了?智能电
    百佳泰测试实验室 2024-12-12 17:33 45浏览
  • 首先在gitee上打个广告:ad5d2f3b647444a88b6f7f9555fd681f.mp4 · 丙丁先生/香河英茂工作室中国 - Gitee.com丙丁先生 (mr-bingding) - Gitee.com2024年对我来说是充满挑战和机遇的一年。在这一年里,我不仅进行了多个开发板的测评,还尝试了多种不同的项目和技术。今天,我想分享一下这一年的故事,希望能给大家带来一些启发和乐趣。 年初的时候,我开始对各种开发板进行测评。从STM32WBA55CG到瑞萨、平头哥和平海的开发板,我都
    丙丁先生 2024-12-11 20:14 68浏览
  • 应用环境与极具挑战性的测试需求在服务器制造领域里,系统整合测试(System Integration Test;SIT)是确保产品质量和性能的关键步骤。随着服务器系统的复杂性不断提升,包括:多种硬件组件、操作系统、虚拟化平台以及各种应用程序和服务的整合,服务器制造商面临着更有挑战性的测试需求。这些挑战主要体现在以下五个方面:1. 硬件和软件的高度整合:现代服务器通常包括多个处理器、内存模块、储存设备和网络接口。这些硬件组件必须与操作系统及应用软件无缝整合。SIT测试可以帮助制造商确保这些不同组件
    百佳泰测试实验室 2024-12-12 17:45 39浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦