广告

C代码的意外

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

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

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

xlAednc

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

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

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

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

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

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

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

xlAednc

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

xlAednc

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

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

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

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

xlAednc

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

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

xlAednc

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

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

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

网友谈经验:xlAednc

@ GeorgeD  xlAednc

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

alpha = beta = gamma = 99;xlAednc

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

那么结果将是:xlAednc

gamma = 99;xlAednc
beta = gamma;xlAednc
beta = 77;xlAednc
alpha = 77xlAednc

但是,在单独赋值时:xlAednc

alpha = 99;xlAednc
beta = 99;xlAednc
gamma = 99;xlAednc

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

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

@ kalpakxlAednc

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

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

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

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

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

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

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

作者介绍:xlAednc

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

xlAednc

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

本文为电子技术设计原创文章,未经授权禁止转载。请尊重知识产权,违者本司保留追究责任的权利。
  • 微信扫一扫
    一键转发
  • 最前沿的电子设计资讯
    请关注“电子技术设计微信公众号”
  • 波兰网友拆德国产电源插排,内部竟是中国制造?! 本文将会介绍LogiLink LPS262U电源插排(接线板)——包含三个USB端口和两个Schuko插座——的内部结构及其简短测试。
  • 仿真器智能,工程师更聪明! 不要过度依赖SPICE仿真器的自动设定,因为过度相信自动化有时可能引发错误。请记得:仿真器智能,工程师更聪明!
  • 可解决工业自动化和IIoT挑战的MCU 工业自动化和工业物联网(IIoT)设计人员的性能要求不断变化。就MCU而言,他们希望获得更快的处理速度、更多的内存、更好的连接性和更多的安全功能。
  • 碳化硅电力电子应用不止于汽车 第三代宽禁带半导体——碳化硅(SiC)——正在发挥其众所周知的潜力,在过去五年内,汽车行业一直是该材料的公开试验场。然而,电气化议程不会以汽车开始和结束。更广泛的运输应用将很快出现,包括卡车和公共汽车、船舶和航运、火车的进一步电气化,甚至飞机。在供电方面,并网太阳能发电系统和通过高压直流链路传输能源,对于低碳能源的生产和分配也至关重要。
  • 波兰网友测试拆解中国产手电筒/手提灯,会不会发起客诉? 本文将对中国制造的COB LED HP1807带移动电源的手提灯/手电筒的内部(包括电池容量)进行简短的测试和分析。在本主题中,我还将展示其电路板上连接的详细草图,这实际上也构成了其原理图。
  • 增强型GaN HEMT的漏极电流特性 增强型GaN基高电子迁移率晶体管(HEMT)已经采用两种不同的结构开发出来。这两种增强型结构是金属-绝缘层-半导体(MIS)结构和栅极注入晶体管(GIT)结构。MIS结构具有受电压驱动的小栅极漏电流,而GIT则具有脊形结构和高阈值电压。两者也都有一些缺点。MIS对栅极干扰的可靠性较低,阈值电压较低,而GIT的栅极开关速度较慢,栅极漏电流较大。
  • 利用反极性MOSFET帮助555振荡器忽略电源和温度变化 恒定频率振荡器是555定时器的经典应用之一。然而,由于所用二极管的特性不理想,占空比的间隔会随着温度和V+电源的变化而变化。本设计实例给出了一种解决方法:利用反极性P沟道MOSFET引导电容的充电电流而不产生任何明显压降。
  • 给电子设计初学者的一些实用技巧 本文将为初学者提供一些实用的布局、提示和技巧,可以帮助您避免事故或解决各种问题。该系列将不定期发布。
  • 为什么步进电机的微步没有想象的那么好? 在使用步进电机设计运动控制系统时,不能假设电机的额定保持转矩在微步时仍然适用,因为增量转矩会大大降低。这可能会导致意外的定位误差。在某些情况下,增加微步分辨率并不能提高系统精度。
  • 适用于CSP GaN FET的简单高性能散热管理解决方案 本文将演示芯片级封装(CSP) GaN FET提供的散热性能为什么至少能与硅MOSFET相当,甚至更胜一筹。GaN FET由于其卓越的电气性能,尺寸可以减小,从而能在不违背温度限制的同时提高功率密度。本文还将通过PCB布局的详细3D有限元仿真对这种行为进行展示,同时还会提供实验验证,对分析提供支持。
  • 波兰网友实测+拆解:中国“最便宜”的太阳能充电器,能否 本文我将对一款最便宜的带有USB 5V输出的中国产太阳能充电器进行实际测试。该充电器采用26cm×14cm的单面板形式,并具有集成转换器——如果可能的话,应产生稳定的5V输出。在这个话题中,我将检查在阳光明媚的3月或4月是否可以用它来为手机充电,然后展示其内部逆变器的样子。测试将从典型的用户角度进行,即我将拿两部手机(三星和苹果),检查它们是否可以在阳光明媚的日子里充电到任何显著程度。
  • 利用GaN技术在狭窄的环境中保持“冷静” 虽然GaN器件可实现更高的功率密度,但为了实现高可靠性的适销对路的适配器设计,仍有一些系统级问题需要解决。这些问题以散热设计和EMI合规性为中心。适配器内的电子电路必须要在放置它们的狭小空间中保持冷(表现出低温升)静(低发射噪声)。本文将着眼于实现这些目标的技术。
广告
热门推荐
广告
广告
EE直播间
在线研讨会
广告
广告
面包芯语
广告
向右滑动:上一篇 向左滑动:下一篇 我知道了