
有讀者問題了類似這樣的問題:while (1) 和 for (;;) 它們不都是無限循環嗎,作用應該一樣啊,它們到底有什么區別?
要回答這個問題,其實你各自編寫一段 while (1) 和 for (;;) 的代碼,編譯對比一下代碼大小和匯編文件,你就大概知道了。
while (1) 和 for (;;) 語法表達
這里先說一下 while (1) 和 for (;;) 語法表達式。
1.while 語法表達
while( 表達式 )
{
語句
}
其中:
表達式:是循環條件
語句:為循環體。
while 語句的語義是:計算表達式的值,當值為真 (非 0) 時, 執行循環體語句。其執行過程可用下圖表示:

2.for 語法表達
for(表達式1; 表達式2; 表達式3)
{
語句
}
它的執行過程如下:
1. 先求解表達式 1
2. 求解表達式 2
若其值為真(非 0),則執行 for 語句中指定的內嵌語句,然后執行下面第 3)步;
若其值為假(0),則結束循環,轉到第 5)步。
3. 求解表達式 3
4. 轉回上面第 2)步繼續執行。
5. 循環結束,執行 for 語句下面的一個語句。
執行過程可用下圖表示:

while (1) 和 for (;;) 異同點
這里先說一下結論,然后再驗證驗證結論。
1. 相同點
作用和效果都一樣:都是實現無限循環的功能。
2. 不同點
while (1):其中括號里面是一個條件,程序會判斷真假。而括號里面的 “1” 永遠是一個 “真值”。
其中,每一次循環,編譯器都要判斷常量 1 是不是等于零。
for (;;):這兩個;;空語句,編譯器一般會優化掉的,直接進入死循環。
根據上面的描述,你可能會覺得:while (1) 比 for (;;) 要做更多事,匯編代碼更多,代碼量也更大。
但事實是這樣嗎?下面驗證一下。
驗證 while (1) 和 for (;;) 差異
我們編寫分別兩個文件 for.c 和 while.c,然后分別生成匯編代碼,看下情況。
1. 源代碼
while.c:
// filename: while.c
intmain(int argc, charconst *argv[])
{
while(1)
{}
return 0;
}
for.c:
// filename: for.c
intmain(int argc, charconst *argv[])
{
for(;;)
{}
return 0;
}
2. 生成匯編
我們這里使用 gcc 編譯器生成匯編,執行命令如下:
gcc -S -o while.s while.c
gcc -S -o for.s for.c
while 匯編代碼:
; filename: whiles
.file "while.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
.L2:
jmp .L2
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 9.3.0"
.section .note.GNU-stack,"",@progbits
for 匯編代碼:
; filename: for.s
.file "for.c"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
.L2:
jmp .L2
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 9.3.0"
.section .note.GNU-stack,"",@progbits
你會發現,除了文件名不同,其余都相同。
當然,這里額外說一下,不同代碼、不同編譯器,以及不同優化等級,可能最終結果有所差異。
文章來源于網絡,版權歸原作者所有,如有侵權,請聯系刪除。

關注【一起學嵌入式】,回復“加群”進技術交流群。
覺得文章不錯,點擊“分享”、“贊”、“在看” 唄!