Расширение и строковое форматирование макроса: как получить имя макроса (а не его значение) в виде строки, используя другой макрос?
Из интереса:
#define _ACD 5, 5, 5, 30
#define DEFAULT_NETWORK_TOKEN_KEY_CLASS _ACD
#define DEFAULT_NETWORK_TOKEN_KEY { DEFAULT_NETWORK_TOKEN_KEY_CLASS }
Используя только макрос DEFAULT_NETWORK_TOKEN_KEY_CLASS, как получить _ACD в виде строки в const без знака char [].
const uint8 startMsg[] = ?? DEFAULT_NETWORK_TOKEN_KEY_CLASS ;
Будет только _ACD.
Что будет правильным расширением макроса для получения _ACD здесь. В контексте Как структурировать макрос, имеющий массив как #define a_macro {5,7,7,97}?
1 ответ
(Здесь применяется стандартная оговорка об отказе от злоупотребления препроцессором C без уважительной причины.)
Конечно, можно делать то, что ты хочешь делать. Тебе необходимо STRINGIFY
макрос и немного косвенности макроса.
Как правило, STRINGIFY
определяется с одним уровнем косвенности, чтобы позволить препроцессору C расширять свои аргументы до того, как они претерпят строковое преобразование. Одна реализация:
/* The # operator converts symbol 'v' into a string */
#define STRINGIFY0(v) #v
#define STRINGIFY(v) STRINGIFY0(v)
Однако вы обнаружите, что этого недостаточно:
#define _ACD 5, 5, 5, 30
#define DEFAULT_NETWORK_TOKEN_KEY_CLASS _ACD
#define DEFAULT_NETWORK_TOKEN_KEY { DEFAULT_NETWORK_TOKEN_KEY_CLASS }
#define START_MSG STRINGIFY(DEFAULT_NETWORK_TOKEN_KEY_CLASS)
const char startMsg[] = START_MSG;
Вот, STRINGIFY(DEFAULT_NETWORK_TOKEN_KEY_CLASS)
расширяется до STRINGIFY0(5,5,5,30)
и препроцессор С жалуется, что вы дали STRINGIFY0
слишком много доводов.
Решение состоит в том, чтобы задержать расширение _ACD
так что расширяется только до 5,5,5,30
когда захочешь. Для этого определите его как функциональный макрос:
#define _ACD() 5, 5, 5, 30
Сюда, _ACD
будет расширен, только когда вы "позвоните": _ACD()
, DEFAULT_NETWORK_TOKEN_KEY_CLASS
теперь расширится до _ACD
и вы должны расширить его, "позвонив": DEFAULT_NETWORK_TOKEN_KEY_CLASS()
,
Следующий код иллюстрирует решение:
#include <stdio.h>
#define STRINGIFY0(v) #v
#define STRINGIFY(v) STRINGIFY0(v)
#define _ACD() 5, 5, 5, 30
#define DEFAULT_NETWORK_TOKEN_KEY_CLASS _ACD
#define DEFAULT_NETWORK_TOKEN_KEY { DEFAULT_NETWORK_TOKEN_KEY_CLASS() }
#define START_MSG STRINGIFY(DEFAULT_NETWORK_TOKEN_KEY_CLASS)
const char startMsg[] = START_MSG;
int main(int argc, char** argv)
{
printf("%s\n",startMsg);
return 0;
}