Учти это:
#define STRINGIFY(A) #A
Если я потом напишу:
STRINGIFY(hello)
Действительно ли компилятор видит это:
#hello
Я думаю, что меня смущает эта дополнительная решетка перед #A
.
Учти это:
#define STRINGIFY(A) #A
Если я потом напишу:
STRINGIFY(hello)
Действительно ли компилятор видит это:
#hello
Я думаю, что меня смущает эта дополнительная решетка перед #A
.
Нет, компилятор поместит аргумент в кавычки, в результате чего:
"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");
Я надеюсь, что это не неясный уголок препроцессора, приводящий к неопределенному поведению, но это не должно быть проблемой, поскольку мы не генерируем другую инструкцию препроцессора.
Вот что видит компилятор:
"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"
РЕДАКТИРОВАТЬ: Как указал Пабби, пример был неправильным, замена макроса так не работает, но теперь я это исправил.
STRINGIFY(CAT(hello,world))
не расширяется до "helloworld"
. Странные правила для расширения аргумента, см. stackoverflow.com/a/8754665/964135
- person Pubby; 23.12.2012
Вы можете проверить это самостоятельно, используя флаг -E
(*) (с gcc/g++):
#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, управляющие препроцессором< /под>
Нашел хорошее, простое объяснение использования хэша в препроцессоре здесь:
http://www.cplusplus.com/doc/tutorial/preprocessor/
[C] stringify
на SO дает множество ответов - person Jens Gustedt   schedule 24.12.2012