web-dev-qa-db-ja.com

引数に展開されるだけのPROTOTYPEマクロのポイントは何ですか?

私は含むヘッダーファイルを持っています

#define PROTOTYPE(s) s

その意味は何ですか?入力自体を置き換えるだけのようです。

周囲には他にも多くのディレクティブがありますが、定義されているかどうかを確認しただけのベアリングがあるように見える唯一のディレクティブは、#ifndef PROTOTYPE。これを行うHDF4ヘッダーファイルの場所をいくつか見つけました:#define PROTOTYPE。それで、それは私の質問を本当に明確にしません。まだかなり役に立たないようです。

使用方法は次のとおりです。

CS_RETCODE clientmsg_callback PROTOTYPE((
CS_CONTEXT * context,
CS_CONNECTION *connection,
CS_CLIENTMSG *clientmsg));

これは、Sybase Open Clientを使用するプロジェクトの一部です。 clientmsg_callbackは後でここで使用されます。

ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB,
                  (CS_VOID *)clientmsg_callback);

ここからサンプルプログラムを終了します。

http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.infocenter.dc35570.1570/html/clcprgde/clcprgde10.htm

clientmsg_callbackは後で実装されます。サンプルは元々C++ではなくCを念頭に置いて作成されたと思います。おそらくそれはそれと関係があるのでしょうか?

81

本当に、本当に初期のCの昔には、プロトタイプのようなものはありませんでした。関数の引数リストは、関数の括弧の後に来ます これのように

square(x)
int x;
{
int y = x * x;
return y;
}

最近では、もちろん、引数は括弧内に入ります:

square(int x)
{
int y = x * x;
return y;
}

「欠落している」戻り値の型に注意してください。 C関数はintを暗黙的に返すために使用されていましたが、別の戻り値の型が必要な場合にのみ、何であるかを言わなければなりませんでした。

関数declarationsには、さらに別のルールセットがありました。 K&R C(古代バージョン)の関数宣言には引数がありませんでした:

int square();

そして、ANSI Cの関数prototypesには引数のリストがあります。

int square(int x);

移行中、人々は奇抜なマクロを使用して両方の方法でコンパイルできるようにしました。

int square(PROTOTYPE(int x));

#define PROTOTYPE(s)

最初のバージョンに拡張されます。

#define PROTOTYPE(s) s

2番目に拡張されます。

質問のコードの「余分な」括弧については、引数リストに複数の引数がある場合に必要です。それらがないと、マクロ呼び出しには複数の引数があるため、1つの引数だけで定義されたマクロとは一致しません。

PROTOTYPE(int x, int y)   // error: too many arguments
PROTOTYPE((int x, int y)) // ok: only one argument (enclosed in parentheses)
129
Pete Becker

このようなマクロは、次のようなことを可能にするために、ヘッダーファイルのプロトタイプで使用されます。

_int foo PROTOTYPE((int bar));
_

ANSI Cが検出された場合(___STDC___は1と定義されています)、これは次のように展開されます。

_int foo(int bar);
_

ANSI Cが検出されなかった場合、これは次のように拡張されます。

_int foo();
_

cが標準化される前は一般的でした。

一部のライブラリはまだこれを行っています。 _tcpd.h_(利用できる場合)を見ると、次のように表示されます。

_/* someone else may have defined this */
#undef  __P

/* use prototypes if we have an ANSI C compiler or are using C++ */
#if defined(__STDC__) || defined(__cplusplus)
#define __P(args)       args
#else
#define __P(args)       ()
#endif
_

これはそれをよく説明しています。

二重括弧については、__P(arg1, arg2)は構文エラーを出し(マクロに渡す引数が多すぎます)、__P((arg1, arg2))は問題ありません(括弧で囲まれた1つだけ)。

これは、GNU Cの__extension__((...))に似ています。GNU以外のコンパイラでは、単に#define __extension__(unused)を使用して、セミポータブルコードを1つの "引数"は括弧でくくられて与えられます。

15
S.S. Anne