Blanktar

  1. top
  2. blog
  3. 2015
  4. 07

C言語のwhileとdo-whileに速度の違いはあるのか。

友人に whileとdo-whileに速度の違いはあるのか? というような質問をされました。 考えたこともなかったので、ちょっと色々やってみました。

とりあえず書いてみたコードがこれ。

#include <stdio.h>

int main(){
    int i=0;

    while(i<1000000000){
        i++;
    }

    return 0;
}

これがwhile版。

#include <stdio.h>

int main(){
    int i=0;

    do{
        i++;
    }while(i<1000000000);

    return 0;
}

こっちがdo-while版。 どちらもほぼ同じで、10億回ループするだけのコードです。

で、GCCでアセンブリにしてみる。

$ gcc -O0 -S while.c

コマンドはこんな感じ。

まずはwhile版。

    .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    $0, -4(%rbp)
    jmp .L2
.L3:
    addl    $1, -4(%rbp)
.L2:
    cmpl    $999999999, -4(%rbp)
    jle .L3
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Gentoo 4.8.4 p1.5, pie-0.6.1) 4.8.4"
    .section    .note.GNU-stack,"",@progbits

ラベル2つも使うんですね。おもしろい。

で、do-while版がこちら。

    .file   "do-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    $0, -4(%rbp)
.L2:
    addl    $1, -4(%rbp)
    cmpl    $999999999, -4(%rbp)
    jle .L2
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Gentoo 4.8.4 p1.5, pie-0.6.1) 4.8.4"
    .section    .note.GNU-stack,"",@progbits

お、ラベルが少ない。 ぱっと見こちらの方がシンプルな仕上がりになっています。行数も少ないし。

なるほど、do-whileの方が速いんだね。・・・とは言い難いので、実測値。 timeコマンドのuserの値を5つ。

while [秒]do-while [秒]
1回目1.6031.601
2回目1.5971.609
3回目1.6111.597
4回目1.6081.597
5回目1.6061.604
平均1.6151.602

・・・うーん。

結論: whileとかdo-whileとかどっちでもいいから、効率的なアルゴリズムを考えなさい。