11

このことを考慮:

  #define STRINGIFY(A) #A

その後、次のように書きます。

 STRINGIFY(hello)

コンパイラは実際にこれを見ていますか?

 #hello

#Aその前に追加のハッシュがあると混乱していると思います。

4

4 に答える 4

17

コンパイラが見ているのはこれです:

"hello"

ハッシュはプリプロセッサのみのトークンです。

単一のハッシュは引数を文字列化します。

#define STRINGIFY(x) #x
STRINGIFY(hello)

に置き換えられます

"hello"

ダブル ハッシュはトークンを連結します。

#define CAT(a, b) a##b
#define _STRINGIFY(x) #x
#define STRINGIFY(x) _STRINGIFY(x)
STRINGIFY(CAT(hello,world))

これに置き換えられます:

_STRINGIFY(helloworld)

そして、これによって:

"helloworld"

編集: Pubby が指摘したように、例は間違っていました。マクロの置換はそのようには機能しませんが、今は修正しました。

于 2012-12-23T13:56:56.747 に答える
11

いいえ、コンパイラは引数を引用符で囲み、次のようにします:

"hello"

#ただし、マクロ置換はandの近くで行われないことに注意してください。その##ため、実際に引数を文字列化する必要がある場合は (別のマクロであっても)、2 つのマクロを作成することをお勧めします。最初のマクロは引数を展開し、もう 1 つは追加します。引用符:

#define STRINGIFY(x) STRINGIFY_AUX(x)
#define STRINGIFY_AUX(x) #x

または、より一般的には、コンパイラが可変長マクロをサポートしている場合 (C99 で導入):

#define STRINGIFY(...) STRINGIFY_AUX(__VA_ARGS__)
#define STRINGIFY_AUX(...) #__VA_ARGS__

引数の先頭にa を貼り付ける関数のようなマクロが本当に必要な場合は#、文字列を生成するためにそれが必要だと思います (そうしないと、コンパイラに対して無効なトークンが作成されます)、2 つの文字列リテラルを簡単に生成できます。コンパイラが「貼り付け」ます:

#include <stdio.h>

#define STRINGIFY(...) STRINGIFY_AUX(__VA_ARGS__)
#define STRINGIFY_AUX(...) #__VA_ARGS__

int main(void)
{
  puts(STRINGIFY(#) STRINGIFY(hello));
}

本体は、プリプロセッサ出力で次のmainようになります。

puts("#" "hello");

これが未定義の動作を引き起こすプリプロセッサのあいまいなコーナーでないことを願っていますが、別のプリプロセッサ命令を生成していないため、問題にはなりません。

于 2012-12-23T14:11:45.380 に答える
10

-E(*)フラグ(gcc / g ++を使用)を使用して、自分でテストできます。

test.cpp

#define STRINGIFY(A) #A

int main(int argc, const char *argv[])
{
    STRINGIFY(hello);
    return 0;
}

の出力g++ test.cpp -E

# 1 "test.cpp"
# 1 "<command-line>"
# 1 "test.cpp"


int main(int argc, const char *argv[])
{
    "hello";
    return 0;
}

(*):If you use the -E option, nothing is done except preprocessing.-プリプロセッサを制御するGCCオプション

于 2012-12-23T14:00:13.553 に答える
3

ここで、プリプロセッサでハッシュを使用するための適切で簡単な説明が見つかりました:

http://www.cplusplus.com/doc/tutorial/preprocessor/

于 2012-12-23T14:07:34.937 に答える