C言語の配列を理解する。

C言語の配列宣言が、バイナリレベルでは全く違う事がわかってきた。次は配列とポインタの違いを探るために、array[i]と*(array + i)の違いを探ってみる。

#include <stdio.h>
#include <stdlib.h>

#define SIZE 5

int main(void)
{
    int i;
    int array[SIZE] = {0, 1, 2, 3, 4};

    for (i = 0; i < SIZE; i++)
        printf("%d ", array[i]);

    puts("");

    for (i = 0; i < SIZE; i++)
        printf("%d ", *(array + i));

    puts("");

    exit(EXIT_SUCCESS);
}

出力されるテキストは変わらない。

gcc -gだけ付けてコンパイルして、objdump -dSで、printf部分を抜き出してみた。

        printf("%d ", array[i]);
 80483f1:       8b 45 f8                mov    0xfffffff8(%ebp),%eax
 80483f4:       8b 44 85 e4             mov    0xffffffe4(%ebp,%eax,4),%eax
 80483f8:       89 44 24 04             mov    %eax,0x4(%esp)
 80483fc:       c7 04 24 40 85 04 08    movl   $0x8048540,(%esp)
 8048403:       e8 cc fe ff ff          call   80482d4 <printf@plt>

        printf("%d ", *(array + i));
 8048427:       8b 45 f8                mov    0xfffffff8(%ebp),%eax
 804842a:       c1 e0 02                shl    $0x2,%eax
 804842d:       89 c2                   mov    %eax,%edx
 804842f:       8d 45 e4                lea    0xffffffe4(%ebp),%eax
 8048432:       01 d0                   add    %edx,%eax
 8048434:       8b 00                   mov    (%eax),%eax
 8048436:       89 44 24 04             mov    %eax,0x4(%esp)
 804843a:       c7 04 24 40 85 04 08    movl   $0x8048540,(%esp)
 8048441:       e8 8e fe ff ff          call   80482d4 <printf@plt>

0xffffffe4(%ebp,%eax,4),%eax なぬぅぅぅ。こんな書き方出来るのか・・・。勉強になった。

GCCの標準では全くといっていいほど最適化は行われていないらしい。

array[i]の方が断然早い。


と、結論づけようとしたが、-O2で最適化した場合、全く同じバイナリが出てきた。

 80483fe:       66 90                   xchg   %ax,%ax

    for (i = 0; i < SIZE; i++)
        printf("%d ", array[i]);
 8048400:       8b 44 9e fc             mov    0xfffffffc(%esi,%ebx,4),%eax
 8048404:       83 c3 01                add    $0x1,%ebx
 8048407:       c7 04 24 40 85 04 08    movl   $0x8048540,(%esp)
 804840e:       89 44 24 04             mov    %eax,0x4(%esp)
 8048412:       e8 bd fe ff ff          call   80482d4 <printf@plt>
 8048417:       83 fb 06                cmp    $0x6,%ebx
 804841a:       75 e4                   jne    8048400 <main+0x40>

ループごとまとめて最適化された。*(array + i)も同様の結果になった。

GCCは最適化オプションを有効にしないとまともな最適化はしない」