1

C++ ファイルの先頭にある定義はプリプロセッサ ディレクティブであることを知っているため、「コードの実際のコンパイルが開始される前にプリプロセッサが実行されるため、ステートメントによってコードが生成される前に、プリプロセッサはこれらすべてのディレクティブをダイジェストします [1]」。

次の簡単な例があるとしたらどうなるでしょうか。

#define PRINT(function) printFnctionName(#function)

void printFnctionName(string name)
{
    cout << name;
}

void test(){};
int main(int argc, char *argv[])
{
    PRINT(test);
}

では、私の質問は、どの関数が渡されるかをプリコンパイラがどのように認識しているのかということです。そして、事前コンパイル/リンク/コンパイルは実際にどのように行われていますか?

また、通常の関数ではなく定義を使用している理由は、関数の名前を取得するためにこの機能を複製する方法を見つけることができなかったためです。

4

3 に答える 3

2

では、私の質問は、どの関数が渡されるかをプリコンパイラがどのように認識しているのかということです。そして、事前コンパイル/リンク/コンパイルは実際にどのように行われていますか?

プリプロセッサは何も知りません。テキストを定義された値に置き換え、渡された値を文字列化するだけです。

したがって、コンパイラは次のように認識します。

void printFnctionName(string name)
{
    cout << name;
}

void test(){};
int main(int argc, char *argv[])
{
    printFnctionName("test");
}
于 2013-01-19T23:31:50.180 に答える
1

プリプロセッサはテキスト置換を行います。あなたの場合、コードは次のように変換されます。

int main(int argc, char *argv[])
{
    printFnctionName("test");
}

プリプロセッサによって、残りのコンパイル プロセスが開始される前に実行されます。プリプロセッサ ディレクティブには単純なものもあれば、はるかに複雑なものもあります (可変アリティ プリプロセッサ ディレクティブなど)。

もちろん、正しいヘッダーファイルなどをインクルードしている必要があります。

于 2013-01-19T23:30:02.200 に答える
0

この特定のケースでは、答えは 2 つの部分に分けられます。その 1 つは、C プリプロセッサは呼び出されている関数について何も認識せず、単にテキストの置換を行うことです。

2 番目の部分は「stringifier」で、#function実際にはtestへの入力として に置き換えられPRINTます"test"。もちろん、関数である必要はありません - printfunction と呼ばれるという理由だけで、次のようにすることができます:

 PRINT(a+b);

そして、あなたはコードを得るでしょう:

 printFnctionName("a+b");   

また

 PRINT(a-*&1,78^%j)

そして得る:

 printFnctionName("a-*&1,78^%j");   

[ uprintFnctionName に抜けがあるのはなぜですか?]

文字列化演算子は、次のような場合に非常に便利です

#define ASSERT(x) do { if (!x) fail_assert(#x, __FILE__, __LINE__); } while(0)

void fail_assert(const char *expr, const char *file, int line)
{
     cerr << "Assertion (" << expr << ") failed at " << file << ":" << line << endl;
}

.... 

ASSERT(ptr != NULL);

"Assertion failed (ptr != NULL) at myprog.cpp:112" というエラー メッセージが表示されますが、これは非常に便利です。

于 2013-01-19T23:45:36.447 に答える