5

ログの目的で、ファイル名と行番号を保持する定数文字列に評価されるマクロを定義しています。

それは正常に動作しますが、2 つの追加マクロが必要な理由がわかりSTRINGIFYませTOSTRING__FILE__ ":" #__LINE__

#include <stdio.h>

#define STRINGIFY(x) #x
#define TOSTRING(x) STRINGIFY(x)
#define THIS_ORIGIN (__FILE__ ":" TOSTRING(__LINE__))

int main (void) {
  /* correctly prints "test.c:9" */
  printf("%s", THIS_ORIGIN);
  return 0;
}

これは私には醜いハックのように思えます。

__LINE__正しく文字列化されるようにステージごとに何が起こるのか、なぜ と のどちらも機能しないのか、誰かが詳細に説明できます__FILE__ ":" STRINGIFY(__LINE__)__FILE__ ":" #__LINE__?

4

2 に答える 2

7

展開順だから。GCCのドキュメントには次のように書かれています:

マクロ引数は、文字列化されるか他のトークンと一緒に貼り付けられない限り、マクロ本体に置換される前に完全にマクロ展開されます。置換後、置換された引数を含むマクロ本体全体が再度スキャンされ、マクロが展開されます。その結果、引数は 2 回スキャンされ、マクロ呼び出しが展開されます。

したがって、引数が文字列化される場合、最初に展開されません。括弧内にリテラル テキストを取得しています。しかし、別のマクロに渡された場合は展開されます。したがって、拡張する場合は、2 レベルのマクロが必要です。

これは、文字列化の前に引数を展開したくない場合があるためです。最も一般的なのはassert()マクロです。あなたが書く場合:

assert(MIN(width, height) >= 240);

メッセージを次のようにします。

Assertion MIN(width, height) >= 240 failed

MIN マクロが展開される非常識なことではありません (gcc では、いくつかの gcc 固有の拡張機能を使用し、非常に長い IIRC です)。

于 2011-09-12T12:56:21.610 に答える
2

__FILE__":"#__LINE__stringify 演算子#はマクロ パラメーターにしか適用できないため、単純に使用することはできません。

__FILE__ ":" STRINGIFY(__LINE__)は他のテキストでも問題なく機能します (たとえば __FILE__ ":" STRINGIFY(foo)、 が、別のマクロ (__LINE__実際にはすべてそうです) をパラメーターとして使用すると機能しません。そうでない場合、そのマクロは置換されません。

于 2011-09-12T12:27:00.437 に答える