0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

聊聊MCU死循环,用for(;;)还是while(1)?

朱老师物联网大讲堂 2024-04-29 08:10 次阅读

点击上方蓝字关注我们首先,问大家一个问题:你们写单片机程序【死循环】时,喜欢用 for(;;) 还是 while(1)? 快来为你喜欢用的【死循环】打call,评论区等你哦~一位工程师发现,国外工程师在给demo在做死循环时用的是for(;;),而不是常用的while(1)。这仅仅是个人习惯的问题,还是有更深层次的含义?

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

f1867d84-05bc-11ef-9118-92fbcf53809c.png大部分网友认为二者并没有什么区别,很多时候,只是心理作用,国外工程师认为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 int main(){ for(;;) { printf("for\n"); }}

生成汇编f195bc5e-05bc-11ef-9118-92fbcf53809c.pngwhile版本:

#includeintmain(){ while(1) { printf("while\n"); }}

生成汇编:f1aa1622-05bc-11ef-9118-92fbcf53809c.png 你会发现,除了文件名不同,其余都相同。当然,这里额外说一下,不同代码、不同编译器,以及不同优化等级,可能最终结果有所差异。f17230c2-05bc-11ef-9118-92fbcf53809c.png

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

f1867d84-05bc-11ef-9118-92fbcf53809c.png不过,有人跳出来反驳,现代编译器的确优化很好,二者运行起来没啥区别,但是实际在嵌入式工作中,尤其是MCU编程中,可没有那么好的编译器。一位工程师表示,很多嵌入式设备只有专用的编译器,而过去这些编译器,尤其是嵌入式编译器没做好优化的情况下,while(1)要比for(;;)多几个语句。因为while里面是判断啊,就会变成:

label: …… mov a, #1 jnz label

这种情况而for(;;)的话一般只会是jmp label。许多人也有类似的经历,并表示,有些私有编译器连 (int)a<<0 这种都能生成非法指令,不由地怀疑配套的破芯片到底能不能受得了各种优化过的指令。f17230c2-05bc-11ef-9118-92fbcf53809c.png

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

f1867d84-05bc-11ef-9118-92fbcf53809c.png也有工程师呼吁,不要学习这种编码风格,现在已经是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(;;)慢,有一定道理,但那都是很早以前的事情了,现在即使没有编译器优化,这种开销也不会成为效率的瓶颈,是不值得优化的,保持代码清晰的静态结构更为重要!f17230c2-05bc-11ef-9118-92fbcf53809c.png

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

f1867d84-05bc-11ef-9118-92fbcf53809c.png公众号博主“WKJay”也在STM32F103、ARMCC5进行过测试,将两个逻辑分别运行一下(不开编译器优化),查看逻辑分析仪输出的结果。while(1) 逻辑运行结果:f2557346-05bc-11ef-9118-92fbcf53809c.png for(;;) 逻辑运行结果:f26ec224-05bc-11ef-9118-92fbcf53809c.png 结果显示,虽然循环体完全相同,但实际运行结果来看,for(;;) 语句执行得更快(45.863ms),比 while(1)(48.643ms) 快了5.7%左右。根据他的分析,for的指令更精简,而while的指令相对更繁琐,简而言之,for抄了近道,而while弯弯绕绕。f27e9f3c-05bc-11ef-9118-92fbcf53809c.png

最后,他开启了编译器的O3优化,结果,二者就几乎不存在差别了(12.505ms):f29169d2-05bc-11ef-9118-92fbcf53809c.png 从可读性角度来说,while(1)简单清晰,for(;;)就模糊多了。不过,对于一些比较老的专用编译器来说,可能就需要慎重考虑使用哪种形式。
对现代编译器来说,二者完全就是一回事,更何况,高主频的芯片不在乎一两条机器指令了,所以这种情况下,怎么顺眼就怎么写。本文转载自公众号|strongerHuang如有侵权 |联系删除

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6037

    文章

    44559

    浏览量

    635449
  • mcu
    mcu
    +关注

    关注

    146

    文章

    17151

    浏览量

    351234
  • 循环
    +关注

    关注

    0

    文章

    92

    浏览量

    15978
收藏 人收藏

    评论

    相关推荐

    为什么while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET)死循环

    为啥while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET)死循环
    发表于 05-14 06:01

    关于死循环语句

    do{..........} while(1) 和for(;;)[..............]这两个语句都代表死循环吧都是一样的意思吧!
    发表于 09-26 17:37

    你怎么样C语言编写死循环

    嵌入式系统中经常要用到无限循环,你怎么样C编写死循环呢?  一、while(1) { }没有划定初始化、更新区域的代码块(位置)。这两项代
    发表于 12-15 07:20

    跳不出的 while 循环

    STM32F103 跳不出的 while 循环
    发表于 12-09 18:38 0次下载

    为什么单片机的主程序是死循环

    任何一个可用程序都必然是死循环程序,这不仅仅是指单片机程序。因为任何微处理器系统一旦开机,系统都在处理内部事件和外设响应,这个过程是一个循环过程,除非关机才能结束这个死循环程序。因此,对于单片机编程必须注意以下几点
    发表于 07-15 17:38 5369次阅读

    单片机的死循环有什么作用

    单片机是可编程器件,在使用时需要编写满足需求的程序。其C语言程序在各个端口、配置初始化完成后,会进入一个死循环,一般while1){;}的形式。初始化完成后,单片机就在
    发表于 08-09 17:01 5739次阅读
    单片机的<b class='flag-5'>死循环</b>有什么作用

    python while循环详解

    python while循环 while 语句用于循环执行程序,即在某条件下,循环执行某段程序,以处理需要重复处理的相同任务。 其基本形式为
    的头像 发表于 02-28 16:39 2456次阅读

    详解Python的for和while循环

    Python 的 for 和 while 循环是灵活并且高级的,语法自然、读起来像伪代码。而 Cython 也支持 for 和 while,无需修改。但由于循环通常占据程序运行时的大部
    的头像 发表于 06-24 16:02 1497次阅读

    while循环

    while 循环定义:“当…时候,执行某段程序”。当给定的条件为真时,执行循环体;条件为假时,结束循环
    的头像 发表于 02-23 14:02 3052次阅读
    <b class='flag-5'>while</b><b class='flag-5'>循环</b>

    详解Python中的while循环

    说起编程语言中的循环,一般 for 循环的时候比较多,因为相比于 while 循环,for 循环
    的头像 发表于 04-26 17:55 1413次阅读

    while循环用法格式

    while循环是一种常用的循环结构,能够按照指定条件多次重复执行一段代码。它的一般用法格式如下: while 条件表达式:循环体 在执行
    的头像 发表于 11-22 10:02 1909次阅读

    c语言在while中嵌套if循环

    C语言是一种广泛使用的面向过程编程语言,它提供了许多控制结构来帮助程序员实现复杂的逻辑和流程控制。其中,while循环和if语句是非常常见和重要的控制结构。本文将详细介绍C语言中在while
    的头像 发表于 11-22 10:09 6204次阅读

    为什么HashMap会产生死循环呢?

    死循环问题发生在 JDK 1.7 版本中,造成这个问题主要是由于 HashMap 自身的运行机制,加上并发操作,从而导致了死循环
    的头像 发表于 12-21 09:06 806次阅读
    为什么HashMap会产生<b class='flag-5'>死循环</b>呢?

    arduino中while循环怎么跳出

    Arduino 是一款开源的硬件平台,广泛应用于各种物联网和嵌入式系统项目。在 Arduino 上编写代码时,循环结构起到了至关重要的作用。而其中的 while 循环更是常用于需要根据特定条件重复
    的头像 发表于 02-14 16:22 2605次阅读

    为何国外工程师偏爱使用for(;;)来实现MCU死循环

    一位工程师发现,国外工程师在给demo在做死循环的是for(;;),而不是常用的while(1)。这仅仅是个人习惯的问题,还是有更深层次
    发表于 04-01 11:26 653次阅读
    为何国外工程师偏爱使用for(;;)来实现<b class='flag-5'>MCU</b><b class='flag-5'>死循环</b>?