Redian新闻
>
MCU做死循环时,到底应该用for(;;) 还是wihile(1)

MCU做死循环时,到底应该用for(;;) 还是wihile(1)

公众号新闻
知乎上,有一个经典问题讨论非常火热。
一位工程师发现,国外工程师在给demo在做死循环时用的是for(;;),而不是常用的while(1)。这仅仅是个人习惯的问题,还是有更深层次的含义?

没啥区别党:都是心理作用 


大部分网友认为二者并没有什么区别,很多时候,只是心理作用,国外工程师认为while需要经过判断括号里的表达式是否非0才跳转。但经过编译器的精心优化以后,while(1)也会被优化成无条件跳转(jmp指令),所以跟for(;;)没什么区别。
有人表示,for(;;)在英语母语者那里很容易跟forever挂钩。
网友解析,也很有可能是习惯问题,其实while(1),还是for(;;)两个语法上有啥区别,那就是for(;;) 明确就是循环,等价于goto一直跳,没有比较条件。
while不编译支持优化的前提下都需要做cmp运算设置寄存器ZF,才能jne,je指令条件跳转。而for(;;)就是明确的jmp无条件转移eip,没有jne,je条件跳转。
不过其实无所谓的,这根本不能提高任何一点代码执行的性能。因为现代编译器大多优化以后跟for(;;)的结果没得什么区别。
其实你所考虑到的一切优化手段,编译器都能帮你完成,因为编译器(尤其是开源的GCC和LLVM)是由来自全球各地的程序员共同研发并改进的,它们的优化能力远远强于你手动改进代码。
也有网友“Shuax”使用mingw编译,实地测试一番:
for版本
#include<stdio.h>int main(){  for(;;)  {    printf("for\n");  }}
生成汇编:
while版本
#include<stdio.h>int main(){  while(1)  {    printf("while\n");  }}
生成汇编:
你会发现,除了文件名不同,其余都相同。
当然,这里额外说一下,不同代码、不同编译器,以及不同优化等级,可能最终结果有所差异。

正方观点:哪有好的编译器


不过,有人跳出来反驳,现代编译器的确优化很好,二者运行起来没啥区别,但是实际在嵌入式工作中,尤其是MCU编程中,可没有那么好的编译器。
一位工程师表示,很多嵌入式设备只有专用的编译器,而过去这些编译器,尤其是嵌入式编译器没做好优化的情况下,while(1)要比for(;;)多几个语句。
因为while里面是判断啊,就会变成:
label:    ……    mov a, #1    jnz label 
这种情况而for(;;)的话一般只会是jmp label。
许多人也有类似的经历,并表示,有些私有编译器连 (int)a<<0 这种都能生成非法指令,不由地怀疑配套的破芯片到底能不能受得了各种优化过的指令。

反方观点:这种代码过时了


也有工程师呼吁,不要学习这种编码风格,现在已经是2024年了,用for(;;)表示无限循环已是一种过时的风格了。
从施特劳斯特撸普博士到我国国家军用标准,均认为 for(;;) 是一种不良风格,可参见:
  • GJB 8114-2013 R-1-9-4:无限循环必须使用while(1)语句,禁止使用for(;;)等其他形式

  • CppCoreGuidelines ES.73:Prefer a while-statement to a for-statement when there is no obvious loop variable

  • 360 safe rules: for语句没有明确的循环变量时应改用while句语

这是为什么呢?在较为严格的规范体系内,for 语句专用于实现具有明确循环次数和循环变量的迭代算法,小括号内的三个表达式应分别专注于循环变量的初始化、循环条件的判断、循环变量的增减,这样可以使循环具有清晰的静态结构,便于阅读,利于维护。如果没有明确的循环变量,则应改用 while 循环,避免对代码的维护者造成误导。
有人说for(;;)表示无条件循环,while(1)需要作条件判断,效率比for(;;)慢,有一定道理,但那都是很早以前的事情了,现在即使没有编译器优化,这种开销也不会成为效率的瓶颈,是不值得优化的,保持代码清晰的静态结构更为重要!
类似于国军标这种严格的代码审计规则,可参见:github.com/Qihoo360/safe-rules

工程师实地测试:和编译器和优化有关


公众号博主“WKJay”也在STM32F103、ARMCC5进行过测试,将两个逻辑分别运行一下(不开编译器优化),查看逻辑分析仪输出的结果。
while(1) 逻辑运行结果:
for(;;) 逻辑运行结果:
结果显示,虽然循环体完全相同,但实际运行结果来看,for(;;) 语句执行得更快(45.863ms),比 while(1)(48.643ms) 快了5.7%左右。
根据他的分析,for的指令更精简,而while的指令相对更繁琐,简而言之,for抄了近道,而while弯弯绕绕。
最后,他开启了编译器的O3优化,结果,二者就几乎不存在差别了(12.505ms):
从可读性角度来说,while(1)简单清晰,for(;;)就模糊多了。不过,对于一些比较老的专用编译器来说,可能就需要慎重考虑使用哪种形式。
对现代编译器来说,二者完全就是一回事,更何况,高主频的芯片不在乎一两条机器指令了,所以这种情况下,怎么顺眼就怎么写。

参考文献

[1] 知乎:https://www.zhihu.com/question/23043337

[2] WKJay:极致的优化,while(1) 与 for(;;) 到底谁更快?.2024.1.28.https://mp.weixin.qq.com/s/T21DLqOkqe38XuG3Z3I8SQ

[3] 嵌入式专栏:单片机代码中while(1) 和 for(;;)有什么区别?.2023.12.1.https://mp.weixin.qq.com/s/mq6sjy1CMPXHIfPpDOt-_A

[4] 嵌入式Linux:你会用while(1)还是for(;;)写循环代码?.2021.1.20.https://mp.weixin.qq.com/s/4Y2x2Xm_0rc9_DwdLgYWMA



最后,最近在做嵌入式就业零基础入门手把手教学,有兴趣的朋友加vx聊:


微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
在西雅图上学,到底选公校还是私校?原来差别这么大...大温房市大震,多项新屋条例出台,到底是福利还是限制?英伟达CUDA护城河,到底有多深?架构升级!车规MCU打响“升级战”,这家本土厂商杀出重围养老金并轨倒计时,到底意味着什么?大温房市大变革,多项新屋条例出台,到底是福利还是限制?吕洪来:取消国务院总理记者会究竟释放了什么政治信号“再见,Terraform”! HashiCorp被收购后,开发者跪求 IBM:不要合并 Terraform 和 Ansible湾区将严查逃避快速道通行费!高达48%被拦截司机利用FasTrak“作弊”,谎称拼车!神奇的催眠,到底是「科学」还是「玄学」?【波士顿市区顶奢公寓|直达BU/NEU/Berklee|地铁绿橘线|近Wholefoods/Star Market】三八妇女节晨游---卖鱼哥终于操刀屠杀,let america be great again代工巨头,也要去卷MCU和SiC纯加法Transformer!结合脉冲神经网络和Transformer的脉冲Transformer | NeurIPS 2023注意! 这些知名快餐店, 都在用F级抗生素肉!国外赚钱国外花,一分别想带回家...从华人富豪,到锒铛入狱的穷光蛋,在美国,到底怎么才能保护自己的小钱钱?同时参加AMC10/12,多此一举还是AIME晋级几率X2?看他们怎么说!...马斯克放大招,最终想实现“零利润”卖车,免费试用FSD风神颂突发!又是Westfield!男子遭狂砍,持刀者在逃!现场紧急封锁美股基本面 - 2024_03_08 * 午报 * 特斯拉工厂火灾疑为恐袭 德国最高检察官接管调查。比特币上涨4% 突破70,在澳洲,现在买房还是等利率下降?听听专家怎么说!到底是“专家”还是“砖家”呢?南昌大风把3人从床上吹下楼,到底是天灾还是人祸?又贵又难选?这届中产家庭挑花了眼的夏令营,到底应该怎么挑本周FOMC焦点:6月会不会降息?今年还能降息三次么?回合制的伊朗以色列冲突,不是WW3季前赛,真正的大戏在亚洲农村墙上的“标语”又火了,寒了9亿农民的心,到底是对还是错?The Firefighter Documenting Sichuan’s Plateau Forest Fires12年前上手深度学习,Karpathy掀起一波AlexNet时代回忆杀,LeCun、Goodfellow等都下场[日签] ​​​哭有时,笑有时; 哀恸有时,起舞有时。Tomcat 调优总结(Tomcat自身优化、Linux内核优化、JVM优化)The Shanghai Temple Offering Noodles for the Soul最佳实践|一文讲解端线程死循环的治理【求职战报】全球金融交易平台Deutsche Börse Systems销售运营面试邀约!两轮游中国 中华大地任我行 高铁边上的农村新貌
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。