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


82

を含むヘッダーファイルがあります

#define PROTOTYPE(s) s

そのポイントは何ですか?入力をそれ自体に置き換えるだけのようです。

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

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

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

これは、Sybase OpenClientを使用するプロジェクトの一部です。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を念頭に置いて書かれたと思います。おそらくそれはそれと関係がありますか?


6
近くあります#if/ #ifdef/ #ifndef/#elseそれは代わりに異なる定義を持っているかもしれないディレクティブは?他のマクロ、特に近く#またはで使用すると、違いが生じる可能性があります##。コメントスタイルのためだけかもしれません。実際に答えるには十分なコンテキストがありません。
aschepler

一般的な答えとして:誰かが変更したい理由があるかもしれないのでPROTOTYPE。役に立たないと思われる奇妙な定義がコードにある場合は、誰かが何かを便利に変更したい場合の潜在的な柔軟性について考えてください。
Apollysはモニカサポート

回答:


130

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

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

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

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

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

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

int square();

また、ANSI Cの関数プロトタイプには、引数のリストがあります。

int square(int x);

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

int square(PROTOTYPE(int x));

#define PROTOTYPE(s)

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

#define PROTOTYPE(s) s

それは秒に拡大します。

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

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

10
ワオ。過去からの爆発。ソフトウェアでの私の最初の仕事の1つは、既存のコードベースからこれらのものを取り除くことでした。Unixのワンライナーテキスト変更プログラムの配列に対する健全な敬意を築き上げました。
user45813 0119

15
それらの定義がどのように機能するのか理解していません#define PROTOTYPE(s)が、入力int x;はどのように変換されxますか?それは私には空の文字列に折り返されるように見えます
Ferrybig

3
@ Ferrybig-すみません、混乱しました。このように定義されるのはプロトタイプです。K&R Cでは、プロトタイプには引数がなく、ANSI Cでは、私たちが見慣れている引数リストのスタイルがあります。
ピートベッカー

1
この方法はまた、に見ることができるzlib.hとzlibライブラリからヘッダOF()マクロ:github.com/madler/zlib/blob/master/zlib.h
ポールBelangerを

@PaulBelanger実際の定義はにありzconf.hます。
SSアン

16

このようなマクロは、ヘッダーファイルのプロトタイプで使用され、次のようなものを許可します。

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つだけです)。

これはGNUCの場合と似て__extension__((...))います。GNU以外のコンパイラで#define __extension__(unused)は、括弧で囲まれた「引数」が1つだけ指定されているため、セミポータブルコードを使用するだけです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.