The Man Who Fell From The Wrong Side Of The Sky:2013年11月14日分

[最新版] [一覧] [前月] [今月] [翌月]

2013/11/14(Thu)

[Unix C][*BSD][申あ絶N] sys/cdefs.hとは何ですか? (その3)

その2では__P()マクロというもので

ことを学びました。

@ K&RとANSI/ISO-Cの関数定義における仮引数の宣言方法の差異

ANSI/ISO-Cでの構文の変更な大きなものとしてもうひとつ、関数定義における仮引数の宣言の方法があります。

まずこちらがK&R

foo(arg1, arg2)
char *arg2;
{
	...
}

bar()
{
	...
}

こいつは

といったところが文法の特徴ですかね、これはALGOLの文法で

integer procedure foo(arg1, arg2);
integer arg1;
value arg2;
begin
	...
end

のように関数定義することの影響ですやね、いやよう知らんけど。

んでこっちがANSI/ISO-C

int
foo(int arg1, char *arg2)
{
	...
}

int
bar(void)
{
	...
}

こっちはいつも見慣れたCのコードですが

という文法ですやね。

@ ソースの後方互換性は?

実はこの関数定義での引数の宣言方法は、ANSI/ISO-CにおいてもK&Rと同じ文法を許容しています。 おかげで「6.9.1 関数定義」あたりの文章が致命的に理解しがたい悪文の見本 *1になっとりますな。

ですのでソースをK&Rのままにしておけばどっちの規格準拠のコンパイラでも問題なくビルドできます。 実際にNet/2のソースを見ると

という状態ですな、 実例

@ 関数定義仮引数のスタイルの現状は?

関数宣言での__P()マクロが抹殺された時よりは緩やかですが、こっちも 索敵殲滅の対象です。 commit logを「 ANSIfy」あたりで引っかけると大量の屍があるんじゃないかな、なぁにノロいからな。

というのもANSI/ISO-C以後に書かれたソースをわざわざK&Rに書き直すようなコストは払えないので K&Rにしか対応してないコンパイラの為にいつまでもそんなメンドイことをやってらんねーつーか。

ところが…

@ DEFUN(), DEFUN_VOID() マクロ (gcc/newlib)

前回も触れたgccの ansidecl.hやnewlibの _ansi.hではやってるんだなこれが。

#if defined (__STDC__) || defined(__cplusplus) || ...
...
#define DEFUN(name, arglist, args)	name(args)
#define DEFUN_VOID(name)		name(void)
#define AND		,
...
#else   /* Not ANSI C.  */
...
#define DEFUN(name, arglist, args)	name arglist args;
#define DEFUN_VOID(name)		name()
#define AND		;
...
#endif  /* ANSI C.  */

こんな感じで使います。

int
DEFUN(foo, (arg1, arg2),
	int arg1 AND
	char *arg2)
{
	...
}

int
DEFUN_VOID(bar)
{
	...
}

もう(可読性もクソも)ないじゃん...

なぜここまでしてK&Rとのソース互換をとることに執心するのか、実例知りたいですな。

@ 次回予告

今回ぜんぜんsys/cdefs.hの話じゃなかったな。

なんかあんまり読んで誰も得しない(書いて俺も仕事しろ)な記事な気がしてきましたが、空気読まずにまだまだK&Rの話は続く予定。


*1:ほーん、お前の口からそれ出るのか。
*2:ただし varargs.h から stdarg.hと可変個引数への移行が絡むところでは事前定義マクロ__STDC__を使って宣言しわけたりはしてます、 これ


[ホームへ] [ページトップへ]