最適化のトリビア

以下のコードがあったとします。

#include <stdio.h>

int main(int argc, char* argv[]){
  int i;
  if(argc > 1){
    i = 10;
  }

  printf("i = %d\n", i);
  return 0;
}

これをgcc 4.1.1でコンパイルして実行すると以下のようになります。

$gcc -O2 main.c
$./a.out
10        <-------注目
$./a.out 1
10
$./a.out 1 2
10

このような結果になるのには、ちゃんとした理由があります(コンパイラの視点にたった場合)。

iに対する代入がない段階において、iの値が何であるかは、Cレベルでは未定義です。これは、代入がない間のiの値をコンパイラが勝手に設定しても問題ないということを意味します。よって、コンパイル時に上のコードを以下のように読み替えても問題ないです。

int main(int argc, char* argv[]){
  int i = 10;
  if(argc > 1){
    i = 10;
  }

  printf("i = %d\n", i);
  return 0;
}

このコードを最適化すると以下のコードになります。

int main(int argc, char* argv[]){
  printf("i = %d\n", 10);
  return 0;
}

よって、a.outのコマンドライン引数に何も与えなくても(argc == 1でも)10が出力されます。

1へぇ。