また「エキスパートCプログラミング」ネタ繋がりです。
自分は"K&R"のC言語本を読んだことが無いので、昔のC言語では関数のプロトタイプ宣言で引数を指定しなかったなんて初めて知りました。
int foo(); int foo(a, b) int a; char b; { ... }
こんな書き方してたんですね・・・。先日NetBSD1.6のsetjmp()の実装調べてた時に"__P"マクロとゆーのに出会い、それ繋がりです。
で、K&R時代のC言語では引数の型が、自動的に格上げされてたみたいです。charとかshortはintへ(ワードより小さいサイズはワード単位へ)、floatはdoubleへ、という具合に、アセンブラレベルで変換されてしまうみたいですね。
一方でANSI時代のC言語では引数の型の格上げはなくなり、charはchar, shortはshort, floatはfloatとしてアセンブラレベルでちゃんと渡されるようになったらしいです。
gccの場合はプロトタイプ宣言で古い書き方もサポートしてはいますが、ANSI-Cとの兼ね合いで引数の格上げがややこしいことになってるっぽいです・・・。
詳しくは "info gcc" -> "C Extension" -> "Function Prototypes"、あるいは下記URLの「プロトタイプ宣言と古い形式の定義」参照。
http://www.sra.co.jp/wingnut/gcc/gcc-j.html
ほか、gccのinfo見てて幾つかオプションの意味を誤解してたのがあったのでメモしておきます。
("info gcc" -> "Invoking GCC" -> "Option Summary")
"-traditional" : てっきり"K&R"のCでコンパイルすると思ってたんですが、厳密には「古いC言語の幾つかの機能をサポートする」、という意味で、ANSI時代の機能も引き続き使える、という意味でした。古いコードの五巻維持が目的で、別に新しい時代の機能が使えなくなる、というわけじゃなかったです。
"-ansi" : こちらは、"ANSI-Cに従わないコードは全部エラーにする"程の強い意味をもってると思ってたんですが、そこまで強くはなかったみたいです。確かにANSI規格と互換性の無いGCCの機能をオフにしたりはするようですが。普通に ANSI規格の機能をサポートする、という意味でした。(加えて"__STRICT_ANSI__"マクロの定義や、幾つかのビルトイン関数が組み込まれなくなったりするようです)
本当に、ANSI-Cに従ってないコードを拒絶/警告するには "-pedantic" オプションを組み合わせるようです。
"-pedantic" : ANSI-CとISO-C++に厳密に準拠した場合に、規格が要求している警告を全て発する。・・・のですが、かといって「じゃぁこれ使えば、ANSI/ISOに従っていないコードは全て拒絶出来る、チェック代わりになるのだが」とは行かないようです。規格の方で「警告メッセージを要求している」ものについては警告を発しますが、適合していなくとも規格の方で警告メッセージを要求していないものについては無視されるようです。
ややこしいですね・・・。
それにしても、C言語って少しディープな世界に首突っ込むと、即座にCPUや機械語(アセンブラ)レベルの知識が絡んできます。ぶっちゃけC言語勉強するなら、アセンブラや電子計算機の歴史を学んでからの方が効率が良いよな気が(最近は)してます・・・。
コメント