點擊上方藍字關注我們首先,問大家一個問題:你們寫單片機程序【死循環】時,喜歡用 for(;;) 還是 while(1)? 快來為你喜歡用的【死循環】打call,評論區等你哦~一位工程師發現,國外工程師在給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 int main(){ for(;;) { printf("for\n"); }}
生成匯編:while版本:
#includeintmain(){ 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(;;)慢,有一定道理,但那都是很早以前的事情了,現在即使沒有編譯器優化,這種開銷也不會成為效率的瓶頸,是不值得優化的,保持代碼清晰的靜態結構更為重要!
四、工程師實地測試:和編譯器和優化有關
公眾號博主“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(;;)就模糊多了。不過,對于一些比較老的專用編譯器來說,可能就需要慎重考慮使用哪種形式。
對現代編譯器來說,二者完全就是一回事,更何況,高主頻的芯片不在乎一兩條機器指令了,所以這種情況下,怎么順眼就怎么寫。本文轉載自公眾號|strongerHuang如有侵權 |聯系刪除
-
單片機
+關注
關注
6043文章
44621瀏覽量
638579 -
mcu
+關注
關注
146文章
17323瀏覽量
352652 -
循環
+關注
關注
0文章
92瀏覽量
16042
發布評論請先 登錄
相關推薦
為什么while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET)死循環?
你怎么樣用C語言編寫死循環呢
為什么單片機的主程序是死循環
單片機的死循環有什么作用
![單片機的<b class='flag-5'>死循環</b>有什么作用](https://file.elecfans.com/web1/M00/C3/5A/o4YBAF8pIvOAFrdoAAByeW_KzK0902.jpg)
python while循環詳解
詳解Python的for和while循環
while循環用法格式
c語言在while中嵌套if循環
arduino中while循環怎么跳出
為何國外工程師偏愛使用for(;;)來實現MCU死循環?
![為何國外工程師偏愛使用for(;;)來實現<b class='flag-5'>MCU</b><b class='flag-5'>死循環</b>?](https://file1.elecfans.com/web2/M00/C7/64/wKgaomYKKiOAK5wZAAARYlyfX1A944.png)
評論