Как получить определение макроса в виде строкового литерала?

Скажите в заголовке, который я не хочу читать сам, но который я действительно включаю, у меня есть

#define A B
#define B C

Теперь

#define STR(name) # name

определяет макрос, который дает мне имя любого макроса в виде строки, а

#define EXP_STR(name) STR(name)

определяет макрос, который дает мне полное расширение любого макроса в виде строки. Так

cout << STR(A) << EXP_STR(A) << endl;

напечатает AC.

Есть ли способ получить "B" из A с помощью некоторых макросов?

Ответ 1

Поскольку вы можете написать

#define B C
#define A B

#define STR(name) # name
#define EXP_STR(name) STR(name)

и

cout << STR(A) << EXP_STR(A) << endl;

будет выводить exaccty одинаково, это означает, что это невозможно.

Когда вы это сделаете

#define A B

а затем

#define B C

теперь это означает, что A будет заменено на C, а не B, поэтому не будет никакого способа сделать это, потому что когда строка cout будет достигнута, препроцессор уже заменил A на C.

Итак, короткий ответ: это невозможно, потому что препроцессор заменил бы A на C перед компиляцией файла.

Ответ 2

Да, это возможно. Вам просто нужно использовать пару читов.

  • #undef B до #define EXP_STR
  • Используйте еще несколько уровней косвенности

Например:

#define A B
#define B C

#define _TEMP_VAR B    // so that it can be redefined later
#undef B               // so that EXP_STR(A) will return "B"

#define EXP_STR__(x) (x)
#define EXP_STR_(x)  EXP_STR__(#x)
#define EXP_STR(x)   EXP_STR_(x)

#define STR(x) # x

#define B _TEMP_VAR    // now you can still access A normally, defined to B (defined to C)

Пробная программа для подтверждения:

#include <stdio.h>

int main(void)
{
    printf( "EXP_STR(A) = %s\n", EXP_STR(A) );
    printf( "STR(A)     = %s\n", STR(A) );
}

Выход:

EXP_STR(A) = B
STR(A)     = A