0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

聊聊MCU死循環(huán),用for(;;)還是while(1)?

朱老師物聯(lián)網(wǎng)大講堂 ? 2024-04-29 08:10 ? 次閱讀

點(diǎn)擊上方藍(lán)字關(guān)注我們首先,問大家一個問題:你們寫單片機(jī)程序【死循環(huán)】時,喜歡用 for(;;) 還是 while(1)? 快來為你喜歡用的【死循環(huán)】打call,評論區(qū)等你哦~一位工程師發(fā)現(xiàn),國外工程師在給demo在做死循環(huán)時用的是for(;;),而不是常用的while(1)。這僅僅是個人習(xí)慣的問題,還是有更深層次的含義?

一、沒啥區(qū)別黨:都是心理作用

f1867d84-05bc-11ef-9118-92fbcf53809c.png大部分網(wǎng)友認(rèn)為二者并沒有什么區(qū)別,很多時候,只是心理作用,國外工程師認(rèn)為while需要經(jīng)過判斷括號里的表達(dá)式是否非0才跳轉(zhuǎn)。但經(jīng)過編譯器的精心優(yōu)化以后,while(1)也會被優(yōu)化成無條件跳轉(zhuǎn)(jmp指令),所以跟for(;;)沒什么區(qū)別。有人表示,for(;;)在英語母語者那里很容易跟forever掛鉤。網(wǎng)友解析,也很有可能是習(xí)慣問題,其實(shí)while(1),還是for(;;)兩個語法上有啥區(qū)別,那就是for(;;) 明確就是循環(huán),等價于goto一直跳,沒有比較條件。while不編譯支持優(yōu)化的前提下都需要做cmp運(yùn)算設(shè)置寄存器ZF,才能jne,je指令條件跳轉(zhuǎn)。而for(;;)就是明確的jmp無條件轉(zhuǎn)移eip,沒有jne,je條件跳轉(zhuǎn)。不過其實(shí)無所謂的,這根本不能提高任何一點(diǎn)代碼執(zhí)行的性能。因?yàn)楝F(xiàn)代編譯器大多優(yōu)化以后跟for(;;)的結(jié)果沒得什么區(qū)別。其實(shí)你所考慮到的一切優(yōu)化手段,編譯器都能幫你完成,因?yàn)榫幾g器(尤其是開源的GCC和LLVM)是由來自全球各地的程序員共同研發(fā)并改進(jìn)的,它們的優(yōu)化能力遠(yuǎn)遠(yuǎn)強(qiáng)于你手動改進(jìn)代碼。也有網(wǎng)友“Shuax”使用mingw編譯,實(shí)地測試一番: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 你會發(fā)現(xiàn),除了文件名不同,其余都相同。當(dāng)然,這里額外說一下,不同代碼、不同編譯器,以及不同優(yōu)化等級,可能最終結(jié)果有所差異。f17230c2-05bc-11ef-9118-92fbcf53809c.png

二、正方觀點(diǎn):哪有好的編譯器

f1867d84-05bc-11ef-9118-92fbcf53809c.png不過,有人跳出來反駁,現(xiàn)代編譯器的確優(yōu)化很好,二者運(yùn)行起來沒啥區(qū)別,但是實(shí)際在嵌入式工作中,尤其是MCU編程中,可沒有那么好的編譯器。一位工程師表示,很多嵌入式設(shè)備只有專用的編譯器,而過去這些編譯器,尤其是嵌入式編譯器沒做好優(yōu)化的情況下,while(1)要比for(;;)多幾個語句。因?yàn)閣hile里面是判斷啊,就會變成:

label: …… mov a, #1 jnz label

這種情況而for(;;)的話一般只會是jmp label。許多人也有類似的經(jīng)歷,并表示,有些私有編譯器連 (int)a<<0 這種都能生成非法指令,不由地懷疑配套的破芯片到底能不能受得了各種優(yōu)化過的指令。f17230c2-05bc-11ef-9118-92fbcf53809c.png

三、反方觀點(diǎn):這種代碼過時了

f1867d84-05bc-11ef-9118-92fbcf53809c.png也有工程師呼吁,不要學(xué)習(xí)這種編碼風(fēng)格,現(xiàn)在已經(jīng)是2024年了,用for(;;)表示無限循環(huán)已是一種過時的風(fēng)格了。從施特勞斯特擼普博士到我國國家軍用標(biāo)準(zhǔn),均認(rèn)為 for(;;)?是一種不良風(fēng)格,可參見:

  • GJB 8114-2013 R-1-9-4:無限循環(huán)必須使用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語句沒有明確的循環(huán)變量時應(yīng)改用while句語

這是為什么呢?在較為嚴(yán)格的規(guī)范體系內(nèi),for 語句專用于實(shí)現(xiàn)具有明確循環(huán)次數(shù)和循環(huán)變量的迭代算法,小括號內(nèi)的三個表達(dá)式應(yīng)分別專注于循環(huán)變量的初始化、循環(huán)條件的判斷、循環(huán)變量的增減,這樣可以使循環(huán)具有清晰的靜態(tài)結(jié)構(gòu),便于閱讀,利于維護(hù)。如果沒有明確的循環(huán)變量,則應(yīng)改用 while 循環(huán),避免對代碼的維護(hù)者造成誤導(dǎo)。有人說for(;;)表示無條件循環(huán),while(1)需要作條件判斷,效率比for(;;)慢,有一定道理,但那都是很早以前的事情了,現(xiàn)在即使沒有編譯器優(yōu)化,這種開銷也不會成為效率的瓶頸,是不值得優(yōu)化的,保持代碼清晰的靜態(tài)結(jié)構(gòu)更為重要!f17230c2-05bc-11ef-9118-92fbcf53809c.png

四、工程師實(shí)地測試:和編譯器和優(yōu)化有關(guān)

f1867d84-05bc-11ef-9118-92fbcf53809c.png公眾號博主“WKJay”也在STM32F103、ARMCC5進(jìn)行過測試,將兩個邏輯分別運(yùn)行一下(不開編譯器優(yōu)化),查看邏輯分析儀輸出的結(jié)果。while(1) 邏輯運(yùn)行結(jié)果:f2557346-05bc-11ef-9118-92fbcf53809c.png for(;;) 邏輯運(yùn)行結(jié)果:f26ec224-05bc-11ef-9118-92fbcf53809c.png 結(jié)果顯示,雖然循環(huán)體完全相同,但實(shí)際運(yùn)行結(jié)果來看,for(;;) 語句執(zhí)行得更快(45.863ms),比 while(1)(48.643ms) 快了5.7%左右。根據(jù)他的分析,for的指令更精簡,而while的指令相對更繁瑣,簡而言之,for抄了近道,而while彎彎繞繞。f27e9f3c-05bc-11ef-9118-92fbcf53809c.png

最后,他開啟了編譯器的O3優(yōu)化,結(jié)果,二者就幾乎不存在差別了(12.505ms):f29169d2-05bc-11ef-9118-92fbcf53809c.png 從可讀性角度來說,while(1)簡單清晰,for(;;)就模糊多了。不過,對于一些比較老的專用編譯器來說,可能就需要慎重考慮使用哪種形式。
對現(xiàn)代編譯器來說,二者完全就是一回事,更何況,高主頻的芯片不在乎一兩條機(jī)器指令了,所以這種情況下,怎么順眼就怎么寫。本文轉(zhuǎn)載自公眾號|strongerHuang如有侵權(quán) |聯(lián)系刪除

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6030

    文章

    44489

    瀏覽量

    631960
  • mcu
    mcu
    +關(guān)注

    關(guān)注

    146

    文章

    16885

    瀏覽量

    349914
  • 循環(huán)
    +關(guān)注

    關(guān)注

    0

    文章

    92

    瀏覽量

    15947
收藏 人收藏

    評論

    相關(guān)推薦

    為什么while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET)死循環(huán)

    為啥while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET)死循環(huán)?
    發(fā)表于 05-14 06:01

    關(guān)于死循環(huán)語句

    do{..........} while(1) 和for(;;)[..............]這兩個語句都代表死循環(huán)吧都是一樣的意思吧!
    發(fā)表于 09-26 17:37

    你怎么樣C語言編寫死循環(huán)

    嵌入式系統(tǒng)中經(jīng)常要用到無限循環(huán),你怎么樣C編寫死循環(huán)呢?  一、while(1) { }沒有劃定初始化、更新區(qū)域的代碼塊(位置)。這兩項(xiàng)代
    發(fā)表于 12-15 07:20

    跳不出的 while 循環(huán)

    STM32F103 跳不出的 while 循環(huán)
    發(fā)表于 12-09 18:38 ?0次下載

    為什么單片機(jī)的主程序是死循環(huán)

    任何一個可用程序都必然是死循環(huán)程序,這不僅僅是指單片機(jī)程序。因?yàn)槿魏挝⑻幚砥飨到y(tǒng)一旦開機(jī),系統(tǒng)都在處理內(nèi)部事件和外設(shè)響應(yīng),這個過程是一個循環(huán)過程,除非關(guān)機(jī)才能結(jié)束這個死循環(huán)程序。因此,對于單片機(jī)編程必須注意以下幾點(diǎn)
    發(fā)表于 07-15 17:38 ?5275次閱讀

    單片機(jī)的死循環(huán)有什么作用

    單片機(jī)是可編程器件,在使用時需要編寫滿足需求的程序。其C語言程序在各個端口、配置初始化完成后,會進(jìn)入一個死循環(huán),一般while1){;}的形式。初始化完成后,單片機(jī)就在
    發(fā)表于 08-09 17:01 ?5668次閱讀
    單片機(jī)的<b class='flag-5'>死循環(huán)</b>有什么作用

    python while循環(huán)詳解

    python while循環(huán) while 語句用于循環(huán)執(zhí)行程序,即在某條件下,循環(huán)執(zhí)行某段程序,以處理需要重復(fù)處理的相同任務(wù)。 其基本形式為
    的頭像 發(fā)表于 02-28 16:39 ?2416次閱讀

    詳解Python的for和while循環(huán)

    Python 的 for 和 while 循環(huán)是靈活并且高級的,語法自然、讀起來像偽代碼。而 Cython 也支持 for 和 while,無需修改。但由于循環(huán)通常占據(jù)程序運(yùn)行時的大部
    的頭像 發(fā)表于 06-24 16:02 ?1454次閱讀

    while循環(huán)

    while 循環(huán)定義:“當(dāng)…時候,執(zhí)行某段程序”。當(dāng)給定的條件為真時,執(zhí)行循環(huán)體;條件為假時,結(jié)束循環(huán)。
    的頭像 發(fā)表于 02-23 14:02 ?2964次閱讀
    <b class='flag-5'>while</b><b class='flag-5'>循環(huán)</b>

    詳解Python中的while循環(huán)

    說起編程語言中的循環(huán),一般 for 循環(huán)的時候比較多,因?yàn)橄啾扔?while 循環(huán),for 循環(huán)
    的頭像 發(fā)表于 04-26 17:55 ?1343次閱讀

    while循環(huán)用法格式

    while循環(huán)是一種常用的循環(huán)結(jié)構(gòu),能夠按照指定條件多次重復(fù)執(zhí)行一段代碼。它的一般用法格式如下: while 條件表達(dá)式:循環(huán)體 在執(zhí)行
    的頭像 發(fā)表于 11-22 10:02 ?1658次閱讀

    c語言在while中嵌套if循環(huán)

    C語言是一種廣泛使用的面向過程編程語言,它提供了許多控制結(jié)構(gòu)來幫助程序員實(shí)現(xiàn)復(fù)雜的邏輯和流程控制。其中,while循環(huán)和if語句是非常常見和重要的控制結(jié)構(gòu)。本文將詳細(xì)介紹C語言中在while
    的頭像 發(fā)表于 11-22 10:09 ?5376次閱讀

    為什么HashMap會產(chǎn)生死循環(huán)呢?

    死循環(huán)問題發(fā)生在 JDK 1.7 版本中,造成這個問題主要是由于 HashMap 自身的運(yùn)行機(jī)制,加上并發(fā)操作,從而導(dǎo)致了死循環(huán)。
    的頭像 發(fā)表于 12-21 09:06 ?695次閱讀
    為什么HashMap會產(chǎn)生<b class='flag-5'>死循環(huán)</b>呢?

    arduino中while循環(huán)怎么跳出

    Arduino 是一款開源的硬件平臺,廣泛應(yīng)用于各種物聯(lián)網(wǎng)和嵌入式系統(tǒng)項(xiàng)目。在 Arduino 上編寫代碼時,循環(huán)結(jié)構(gòu)起到了至關(guān)重要的作用。而其中的 while 循環(huán)更是常用于需要根據(jù)特定條件重復(fù)
    的頭像 發(fā)表于 02-14 16:22 ?2277次閱讀

    為何國外工程師偏愛使用for(;;)來實(shí)現(xiàn)MCU死循環(huán)

    一位工程師發(fā)現(xiàn),國外工程師在給demo在做死循環(huán)的是for(;;),而不是常用的while(1)。這僅僅是個人習(xí)慣的問題,還是有更深層次
    發(fā)表于 04-01 11:26 ?529次閱讀
    為何國外工程師偏愛使用for(;;)來實(shí)現(xiàn)<b class='flag-5'>MCU</b><b class='flag-5'>死循環(huán)</b>?