广告

C代码的意外

2021-06-25 14:25:53 Colin Walls 阅读:
C语言可以用多种不同的方式编写代码,但是完成完全一样的功能。但是有一个问题:有时候两段语句虽然表面上看起来实现完全一样的功能,实际却有细微的差别。

C语言非常灵活、更容易表达,这是C语言很成功并且一直没被“更好的”语言取代的一个原因。例如,其灵活性的一个表现就是,可以用多种不同的方式编写代码,但是完成完全一样的功能,因此每个人可以根据自己的喜好而形成不同的编码风格。但是有一个问题:有时候,两段代码虽然表面上看起来能完成同样的功能,但是却有细微的差别。这种情况可能在最简单的代码中发生,本文将探讨一些可能发生的情况。41Rednc

在C语言中,利用几种不同的方式来完成同一件事,这是很常见的,这些方式达到的效果完全相同。例如,假设x是一个普通的int变量,以下每个语句都将完成同项的任务:41Rednc

41Rednc

使用其中的每一种方法,x都会加1。唯一可能的区别是,能力较弱的编译器可能会为后两种方法生成稍好一些的代码(这说明得到更好的编译器是值得的)。41Rednc

上面两种形式的++运算符会产生相同的结果。但是,如果表达式的结果作为中间值被使用,那么前增量和后增量是不同的,因此:41Rednc

y=x++; // y在增量前被赋值 41Rednc

y=++x; // y在增量后被赋值 41Rednc

有趣的是,后增量稍微“昂贵”一些,因为需要分配存储空间以保留x的旧值。但是,编译器可能会对此进行优化。如果在不使用表达式的值时分配存储,那么肯定需要一个新的编译器!41Rednc

如果x不是int值自身,而是指向int值的指针,则加1会产生指针地址加4(在32位机器上)的效果。如果你对此感到惊讶,就有必要复习一下指针运算了。然而,有时看似等效的表达方式会有非常细微的差异……41Rednc

对任何编程语言来说,你能做的最简单的事可能就是为变量赋值。所以,使用C语言时,我们可以这样写:41Rednc

41Rednc

当然,也可以更紧凑地写成这样:41Rednc

41Rednc

它们是100%等效的,对吗?大多数情况下,这两种表达方式是完全等效的,但是(至少)在四种情况下,选择一种或另一种可能会有不同:41Rednc

首先,也是最平淡无奇的,每个变量都是独立的,这时或许加个注释,说明为什么将其设置为该值比较合适。41Rednc

其次,编写可维护的代码肯定比较好。也许在将来的某个时候,可能需要更改代码,使这三个变量都设置为不同的值。第一种格式更容易修改。41Rednc

第三个原因是当编译器不合标准时,可能会为第一种形式的语句生成这样的代码:41Rednc

41Rednc

第二种语句会提示r0只需要加载一次。同样,更好的编译器不需要提示。41Rednc

最后是执行顺序的问题。在第一种语句中,很明显将先赋值alpha,最后赋值gamma。编译器会这样解释第二种语句:41Rednc

41Rednc

这意味着赋值顺序颠倒了。但有关系吗?大多数时候,没有。但如果这些是设备寄存器,而不是普通变量,就可能会有很大的不同。硬件需要设置值然后按精确的顺序加载,这是很常见的。41Rednc

所以我想说,应该避免在一个语句中多次赋值。41Rednc

总之,虽然C是一种轻量型编程语言,但如果简化完成任务的方式,C语言还可以更变得轻,从而可能产生更清晰、更易于维护的代码。41Rednc

网友谈经验:41Rednc

@ GeorgeD  41Rednc

产生意外的另一个主要原因是中断。例如,在赋值顺序的例子中:41Rednc

alpha = beta = gamma = 99;41Rednc

有可能在beta被赋值99之后,一个中断立马重新将其赋值为77。41Rednc

那么结果将是:41Rednc

gamma = 99;41Rednc
beta = gamma;41Rednc
beta = 77;41Rednc
alpha = 7741Rednc

但是,在单独赋值时:41Rednc

alpha = 99;41Rednc
beta = 99;41Rednc
gamma = 99;41Rednc

只有beta被中断重新赋值为 77。 41Rednc

人们会期望这个复合语句中具有一些原子性,但这在C语言中没有定义。程序员可以在复合语句的执行期间禁用中断,如果他愿意的话。41Rednc

@ kalpak41Rednc

我会说这些意外是源于“聪明过分”的代码。41Rednc

现实中一个程序员需要写多少次“alpha = beta = gamma = 99;”?41Rednc

换句话说,与所带来的风险相比,此类优化代码的优化产生的好处有多大?41Rednc

此外,这样的赋值使注释变得困难,因此可读性很差。41Rednc

当程序员编写这样的代码时,我会质疑架构师和设计师的能力。41Rednc

在过去的日子里,内存不足且时钟还是KHz,有时不得不为了解析效率而牺牲可读性。41Rednc

而现在有非常好的优化编译器可用,内存充足,处理器速度达到 100 MHz,我们必须说这些代码是不安全的或错误的。41Rednc

作者介绍:41Rednc

Colin Walls是西门子公司Mentor的嵌入式软件技术专家,拥有超过40年电子行业的经验,主要专注于嵌入式软件。他经常在大会和研讨会上发表演讲,并撰写了大量技术文章和两本关于嵌入式软件的书籍。41Rednc

41Rednc

(原文刊登于Aspencore旗下embedded网站,参考链接:Surprises in C code,由Jenny Liao编译。)41Rednc

本文为电子技术设计原创文章,未经授权禁止转载。请尊重知识产权,违者本司保留追究责任的权利。
  • 微信扫一扫
    一键转发
  • 最前沿的电子设计资讯
    请关注“电子技术设计微信公众号”
  • 一种用于电路板回收的新基材:遇水能溶 英国的Jiva Materials公司开发了一种新型的PCB基材Soluboard,这种基材是由天然纤维包裹在一种无卤的聚合物中制成的,与行业内经常使用的FR-4基材不同,这种材料只要在90摄氏度左右的热水中浸泡30分钟,就可以分层溶解···
  • 机器人版的ChatGPT,谷歌新模型泛化能力大幅提高 7月28日,Google DeepMind宣布以训练AI聊天机器人的方式训练了一款全新的机器人模型Robotic Transformer 2(RT-2),这是一种新颖的视觉-语言-动作(VLA)模型,可以从网络和机器人数据中学习,并将这些知识转化为机器人控制的通用指令。
  • 英伟达惨遭背刺,这个SDK让AMD平台也能运行CUDA 近日,AMD正式推出了HIP SDK,这是ROCm生态系统的一部分,基于开源ROCm解决方案,HIP SDK使消费者可以在各类GPU上运行CUDA应用,为专业和消费级GPU提供CUDA支持。
  • 如何用软件定义无线电实现更有效的核磁共振成像仪设计 在本文中,我们讨论了MRI的基本概念,以及如何将SDR集成到这些系统中以提高性能和功能。我们介绍了一些适用于MRI应用的SDR规范,以及对MIMO射频通道的支持。还讨论了让SDR成为高性能射频单元的原因,以及高信噪比和MIMO通道之间的高相位相干性。
  • 电池能用三十年?美国Ener Venue称推出革命性电池技术 三元锂离子电池的理论寿命约为800次循环,磷酸铁锂约为2000次,而钛酸锂据说可以达到1万次循环,也就是说常规普通人使用的锂离子电池每天完全充放电三次,最多也就能用上几年的时间。虽然相较于铅酸电池200-300次的循环寿命来说,这已经是很大幅度的提升了,但现在有一家公司宣称他们的电池可以充放电30000次,每天充放电三次,能用30年。
  • 测试中比友商温度低14度,一加天工散热系统怎么做到的? 7月27日,一加在2023年ChinaJoy上发布了全球首创的散热技术,即航天级三维立体散热系统“天工散热系统”,这是一加的又一次新的尝试,让我们一起来了解一下。
  • 万物电气化:探索绿色未来之路 在本文中,我们将重点介绍美国年度脱碳展望(ADP)2022报告中的一些重要发现。本报告着眼于实现净零经济的各种情景。我们在本文中重点关注的方法称为“中心情景”,它遵循到2050年实现净零排放的时间表。
  • 闪存控制器在医疗安全中的作用简述 与大多数其他领域不同,对医疗设备的攻击可能危及人们的健康甚至生命,特别是当有大量医疗设备联网以便对患者实现更好的监控和管理时。这包括药物输液泵、心脏起搏器,以及监测心率、血压和其他生命体征的设备。
  • 后来居上,美光宣布已出样业界首款HBM3 Gen2内存 7月26日,美光宣布推出业界首款8层24GB HBM3 Gen2内存芯片,是HBM3的下一代产品,采用1β工艺节点,目前该款美光内存芯片正在向客户提供样品。
  • 韩国造世界首个室温超导体,闹剧还是新的未来? 7月22日,韩国的一个科研团队在预印本网站arXiv平台上上传了两篇论文,声称发现了世界上首个常压室温超导体,这种材料是一种改性铅磷灰石名为LK-99,超导临界温度在127摄氏度,即400K以上,而且在常压下就具备超导性。
  • 基于软件的无线输电建模方法 本文探讨了无线输电(WPT)在电动汽车(EV)充电、手机充电以及医疗设备等应用中的作用。
  • 下一个医疗前沿:网联可穿戴设备 医疗和消费级可穿戴设备将继续增强连接性和电池寿命,以实现对血压、体温和身体水分等多种生物标志物的实时和非侵入性监测。
广告
热门推荐
广告
广告
EE直播间
在线研讨会
广告
广告
面包芯语
广告
向右滑动:上一篇 向左滑动:下一篇 我知道了