2017-09-08 13 views
2

コードを解析しながら次のマクロにぶつかりました。わかりにくいCマクロ

#define __COMMAND_HANDLER(name, extra ...) int name(struct command_invocation *cmd, ## extra) 

name__COMMAND_HANDLERに引数として渡される関数は、しかし、どこか他のコードでこの関数の定義が無いです。 cmd引数のタイプ(command_invocation)が定義されています。基本的に私はこのマクロの機能を理解できませんでした。なぜなら、関数nameの定義を見つけることができなかったからです。名前は、標準のCライブラリであらかじめ定義された関数のようなものですか? nameが定義されていない場合、このマクロ定義は意味がありますか?

+1

マクロ定義は標準Cではありません。それはGNU拡張を使用しています。トリプルドットの前にカンマがあり、それが標準マクロだったとします。また、二重アンダースコア(またはアンダースコアと大文字)で始まる名前は、 '実装'によって使用するために予約されています。自分のコードにそのようなマクロを定義するべきではありません。 –

答えて

1

・ダーニングのpreprocession、プリプロセッサを使用すると、指定されたトークンにその本体の内側にnameextra...の各出現箇所を置き換えると、その本体に__COMMAND_HANDLER(name, extra ...)マクロのすべての出現を置き換えます。

これは、name引数に入力するものはすべて関数名になり、extra...は最初のパラメータ(struct command_invocation *cmd)の追加パラメータになります。例えば

次の行:前処理後の

__COMMAND_HANDLER(foo, int param) { 
    /* definition */ 
} 

は次のようになります。

int foo(struct command_invocation *cmd, int param) { 
    /* definition */ 
} 

一つ重要なことが明らかにされていますextra##extra...の代わりを使用して、可変引数(命名...)は、標準の一部ではありませんが、GNU extensionsです。コンマの後の##の効果は、可変引数に何も指定しないようにします。次のようにそれが使われているとき(-pedanticフラグ付き)GCCとあなたの例をコンパイルすると、あなたは、警告メッセージが表示されます。##演算子の両側に2つのトークンがある。すなわち

/* The following example will print the following messages: 
* warning: ISO C does not permit named variadic macros [-Wvariadic-macros] 
* warning: ISO C99 requires at least one argument for the "..." in a variadic 
* macro 
*/ 
__COMMAND_HANDLER(bar); 

は通常##は、トークンの連結のための演算子です単一のものに結合される。要するに

#include <stdio.h> 
#define FOO(name, number) void name##number() 

FOO(bar, 1) { puts("I'm first."); } 
FOO(bar, 2) { puts("I'm second."); } 

int main() { 
    bar1(); 
    bar2(); 
    return 0; 
} 
0

これはマクロであり、名前はパラメータです。前処理段階で

__COMMAND_HANDLER(hello, char* world) 

を、それはにあなたのコードを変換するでしょう:あなたはこのようにそれを使用 この場合

int hello(struct command_invocation *cmd, char *world); 

、名前がこんにちは、と余分= CHAR *世界として渡されます。 余分に何かを渡さないと、##はコンマを破棄します。

+0

'##'と組み合わせて '...'の効果を詳しく記述してください。 – Yunnosch

0

:たとえば、マクロは、extra ...によって指定されたパラメータname及び任意の追加引数で指定された名前の関数を作成します。

注:二重のアンダースコアで始まる名前は実装が予約されているため、使用しないでください。

マクロは可変です。

マクロextra ...の2番目の引数は、関数宣言マクロ内のデフォルトの__VA_ARGS__の代わりに使用する名前を提供します。これはGNU拡張である

## extraは、マクロ__COMMAND_HANDLERの2番目の引数が省略されている場合、前のカンマを削除し、その関数を使わずに呼び出すことができるプリプロセッサを指定するGNU拡張です。

nameという宣言が見つからない理由は、それがマクロのパラメータだからです!マクロ自体は名前に何が入っていても新しい関数を宣言しており、デフォルトの最初の引数はstruct command_invocation *cmdです。ここで

は、いくつかの例は以下のとおりです。

呼び出し:呼び出しに対し
int cmd(struct command_invocation *cmd,char * w)


__COMMAND_HANDLER(cmd2)
するの関数宣言につながる
__COMMAND_HANDLER(cmd,char * w)
はの関数宣言につながります:
int cmd2(struct command_invocation *cmd)

関連する問題