gcc さんのよくわからない挙動

builtin 関数

golf のときは普通 #include せずに書くわけだけど,引数として関数を渡そうとすると undeclared と言われてしまう.
…なんかうまく説明できないので例で示すと,

main(){printf("hello\n");}

のように,関数を呼び出す形で使用する場合は imcompatible implicit declaration of built-in function ' printf' という warning は出るけどコンパルはできる.
一方,

main(){printf("%p\n",puts);}

のように,builtin 関数を引数として渡そうとすると ' puts' undeclared という error が出てコンパイルできない.


まぁ

main(){printf("%p\n",__builtin_puts);}

として明示的に builtin 関数を使用したり,

main(){printf("%p\n",printf);}

のように,それより前に使った関数ならコンパイル通る模様.

関数呼び出しが消される

f(s){strcmp(s,"t");}main(){printf("%d\n",f("s"));}

これをコンパイルして f のアセンブリを見てみると,

_f:
00001fbe        pushl   %ebp
00001fbf        movl    %esp,%ebp
00001fc1        subl    $0x08,%esp
00001fc4        leave
00001fc5        ret

となっていて,見事に strcmp が無かったことになっている.
最適化を無くした状態でこれってどうなんだろう…


見つけた解決法としては,

f(s){-strcmp(s,"t");}

とすると,

_f:
00001f9a        pushl   %ebp
00001f9b        movl    %esp,%ebp
00001f9d        pushl   %ebx
00001f9e        subl    $0x14,%esp
00001fa1        calll   0x00001fa6
00001fa6        popl    %ebx
00001fa7        leal    0x0000004f(%ebx),%eax
00001fad        movl    %eax,0x04(%esp)
00001fb1        movl    0x08(%ebp),%eax
00001fb4        movl    %eax,(%esp)
00001fb7        calll   0x0000300a      ; symbol stub for: _strcmp
00001fbc        addl    $0x14,%esp
00001fbf        popl    %ebx
00001fc0        leave
00001fc1        ret

となって,strcmp がちゃんと呼ばれるようになった.
C のコードを見ると符号が反転されてしまうように見えるが,アセンブリを見ての通り何故かそんなことはない.
なんでこうなるんだろう.すごい不思議だけど,gcc のソースを見る勇気と根気は無い…