很早以前(DOS+win98时代),我被教育说while比for循环效率高。当时测试的结果也确实是。但测试用例忘记了。现在,如下2个函数,算法是一样的,执行效果也一样

int log2_while(int n){
int res = 0;
while((n>>=1))
    res++;
return res;
}
int log2_for2(int x)
{
for(int i=0;;i++)
 if((x>>=1)==0)
 return i;
}

执行效果

--第1遍
use for2        199229440,234ms(慢)
use while       199229440,219ms

use for2        335544480,344ms(慢)
use while       335544480,327ms
--第2遍
use for2        199229440,234ms
use while       199229440,234ms

use for2        335544480,328ms
use while       335544480,343ms(慢)

这里看到cl有个FA选项可以输出生成的asm 下面把这个cpp文件的asm显示如下

01. #include 
02. int log2_while(int n){
03. int res = 0;
04. while((n>>=1))
05.     res++;
06. return res;
07. }
08. int log2_for2(int x)
09. {
10. for(int i=0;;i++)
11.  if((x>>=1)==0)
12.  return i;
13. }
14. void main()
15. {
16. log2_while(64);
17. }

; Listing generated by Microsoft (R) Optimizing Compiler Version 17.00.51106.1 

    TITLE    D:\log2_fw.cpp
    .686P
    .XMM
    include listing.inc
    .model    flat

INCLUDELIB LIBCMT
INCLUDELIB OLDNAMES

PUBLIC    ?log2_while@@YAHH@Z                ; log2_while
PUBLIC    ?log2_for2@@YAHH@Z                ; log2_for2
PUBLIC    _main
; Function compile flags: /Odtp
_TEXT    SEGMENT
_main    PROC
; File d:\log2_fw.cpp
; Line 15
    push    ebp
    mov    ebp, esp
; Line 16
    push    64                    ; 00000040H
    call    ?log2_while@@YAHH@Z            ; log2_while
    add    esp, 4
; Line 17
    xor    eax, eax
    pop    ebp
    ret    0
_main    ENDP
_TEXT    ENDS
; Function compile flags: /Odtp
_TEXT    SEGMENT
_i$1 = -4                        ; size = 4
_x$ = 8                            ; size = 4
?log2_for2@@YAHH@Z PROC                    ; log2_for2
; File d:\log2_fw.cpp
; Line 9
    push    ebp
    mov    ebp, esp
    push    ecx
; Line 10
    mov    DWORD PTR _i$1[ebp], 0
    jmp    SHORT $LN4@log2_for2
$LN3@log2_for2:
    mov    eax, DWORD PTR _i$1[ebp]
    add    eax, 1
    mov    DWORD PTR _i$1[ebp], eax
$LN4@log2_for2:
; Line 11
    mov    ecx, DWORD PTR _x$[ebp]
    sar    ecx, 1
    mov    DWORD PTR _x$[ebp], ecx
    jne    SHORT $LN1@log2_for2
; Line 12
    mov    eax, DWORD PTR _i$1[ebp]
    jmp    SHORT $LN5@log2_for2
$LN1@log2_for2:
; Line 13
    jmp    SHORT $LN3@log2_for2
$LN5@log2_for2:
    mov    esp, ebp
    pop    ebp
    ret    0
?log2_for2@@YAHH@Z ENDP                    ; log2_for2
_TEXT    ENDS
; Function compile flags: /Odtp
_TEXT    SEGMENT
_res$ = -4                        ; size = 4
_n$ = 8                            ; size = 4
?log2_while@@YAHH@Z PROC                ; log2_while
; File d:\log2_fw.cpp
; Line 2
    push    ebp
    mov    ebp, esp
    push    ecx
; Line 3
    mov    DWORD PTR _res$[ebp], 0
$LN2@log2_while:
; Line 4
    mov    eax, DWORD PTR _n$[ebp]
    sar    eax, 1
    mov    DWORD PTR _n$[ebp], eax
    je    SHORT $LN1@log2_while
; Line 5
    mov    ecx, DWORD PTR _res$[ebp]
    add    ecx, 1
    mov    DWORD PTR _res$[ebp], ecx
    jmp    SHORT $LN2@log2_while
$LN1@log2_while:
; Line 6
    mov    eax, DWORD PTR _res$[ebp]
; Line 7
    mov    esp, ebp
    pop    ebp
    ret    0
?log2_while@@YAHH@Z ENDP                ; log2_while
_TEXT    ENDS
END

改成这样,for和while的语义应该都一样了。汇编还是有所不同。

01. #include 
02. int log2_while(int n){
03. int res = 0;
04. while((n>>=1))
05.     res++;
06. return res;
07. }
08. int log2_for2(int x)
09. {int i=0;
10. for(;x>>=1;i++);
11.  return i;
12. }
13. void main()
14. {
15. log2_while(64);
16. }

; Function compile flags: /Odtp
_TEXT    SEGMENT
_i$ = -4                        ; size = 4
_x$ = 8                            ; size = 4
?log2_for2@@YAHH@Z PROC                    ; log2_for2
; File d:\test_fw.cpp
; Line 9
    push    ebp
    mov    ebp, esp
    push    ecx
    mov    DWORD PTR _i$[ebp], 0
    jmp    SHORT $LN4@log2_for2
$LN2@log2_for2:
; Line 10
    mov    eax, DWORD PTR _i$[ebp]
    add    eax, 1
    mov    DWORD PTR _i$[ebp], eax
$LN4@log2_for2:
    mov    ecx, DWORD PTR _x$[ebp]
    sar    ecx, 1
    mov    DWORD PTR _x$[ebp], ecx
    je    SHORT $LN3@log2_for2
    jmp    SHORT $LN2@log2_for2
$LN3@log2_for2:
; Line 11
    mov    eax, DWORD PTR _i$[ebp]
; Line 12
    mov    esp, ebp
    pop    ebp
    ret    0
?log2_for2@@YAHH@Z ENDP                    ; log2_for2
_TEXT    ENDS
; Function compile flags: /Odtp
_TEXT    SEGMENT
_res$ = -4                        ; size = 4
_n$ = 8                            ; size = 4
?log2_while@@YAHH@Z PROC                ; log2_while
; File d:\test_fw.cpp
; Line 2
    push    ebp
    mov    ebp, esp
    push    ecx
; Line 3
    mov    DWORD PTR _res$[ebp], 0
$LN2@log2_while:
; Line 4
    mov    eax, DWORD PTR _n$[ebp]
    sar    eax, 1
    mov    DWORD PTR _n$[ebp], eax
    je    SHORT $LN3@log2_while
; Line 5
    mov    ecx, DWORD PTR _res$[ebp]
    add    ecx, 1
    mov    DWORD PTR _res$[ebp], ecx
    jmp    SHORT $LN2@log2_while
$LN3@log2_while:
; Line 6
    mov    eax, DWORD PTR _res$[ebp]
; Line 7
    mov    esp, ebp
    pop    ebp
    ret    0
?log2_while@@YAHH@Z ENDP                ; log2_while
_TEXT    ENDS
END