Что видит компилятор с этим макросом?

Учти это:

  #define STRINGIFY(A) #A

Если я потом напишу:

 STRINGIFY(hello)

Действительно ли компилятор видит это:

 #hello

Я думаю, что меня смущает эта дополнительная решетка перед #A.


person johnbakers    schedule 23.12.2012    source источник


Ответы (4)


Нет, компилятор поместит аргумент в кавычки, в результате чего:

"hello"

Однако имейте в виду, что подстановка макросов не происходит рядом с # и ##, поэтому, если вам действительно нужно преобразовать аргумент в строку (даже если это другой макрос), лучше написать два макроса, первый для разверните аргумент, а другой, чтобы добавить кавычки:

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

Или, в более общем случае, если ваш компилятор поддерживает вариативные макросы (представленные в C99):

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

Если вам действительно нужен функциональный макрос, который вставляет # в начало аргумента, я думаю, вам нужно сгенерировать строку (в противном случае вы сделаете недопустимый токен для компилятора), поэтому вы можете просто сгенерировать две строки литералы, которые компилятор "вставит":

#include <stdio.h>

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

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

Тело main будет выглядеть в выводе препроцессора следующим образом:

puts("#" "hello");

Я надеюсь, что это не неясный уголок препроцессора, приводящий к неопределенному поведению, но это не должно быть проблемой, поскольку мы не генерируем другую инструкцию препроцессора.

person effeffe    schedule 23.12.2012

Вот что видит компилятор:

"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"

РЕДАКТИРОВАТЬ: Как указал Пабби, пример был неправильным, замена макроса так не работает, но теперь я это исправил.

person milleniumbug    schedule 23.12.2012
comment
Ну, это здорово, можете ли вы объяснить, что именно хэш делает с OP, чтобы сделать этот ответ несколько полезным? - person Richard J. Ross III; 23.12.2012
comment
я согласен, я все еще в замешательстве. второй хэш также интерпретируется препроцессором, поэтому, по сути, препроцессор выполняет две интерпретации при использовании STRINGIFY? - person johnbakers; 23.12.2012
comment
@andrewx Хэш предназначен только для того, чтобы препроцессор упорядочил это. - person milleniumbug; 23.12.2012
comment
Временный -1, так как STRINGIFY(CAT(hello,world)) не расширяется до "helloworld". Странные правила для расширения аргумента, см. stackoverflow.com/a/8754665/964135 - person Pubby; 23.12.2012

Вы можете проверить это самостоятельно, используя флаг -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, управляющие препроцессором< /под>

person Vincenzo Pii    schedule 23.12.2012

Нашел хорошее, простое объяснение использования хэша в препроцессоре здесь:

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

person johnbakers    schedule 23.12.2012