#c #macros #concatenation #c-preprocessor
#c #макросы #сцепление #c-препроцессор
Вопрос:
Пожалуйста, ознакомьтесь с сокращенным кодом на языке си ниже и ознакомьтесь с комментариями. Есть ли в любом случае способ сделать это возможным? Знает ли уже препроцессор, что spn_1 = 18? Можно ли в любом случае использовать значение spn_1 в качестве имени токена?
#define TEST_M(_spn) struct astruct _test_struct_##_spn = { .spn = _spn, }; enum spns { spn_1 = 18, }; struct astruct { int spn; }; TEST_M(spn_1) // What I want: // struct astruct _test_struct_18 = { .spn = 18, }; // What I get: // struct astruct _test_struct_spn_1 = { .spn = 18, }; // I can do, but I want attach a name to 18: // TEST_M(18)
Комментарии:
1. Перечисление не является константой предварительного процессора, поэтому вы не можете расширить его до целочисленной константы на этапе предварительного процессора.
Ответ №1:
Поскольку вы хотите, чтобы препроцессор заменил токен на его значение, для этого вам нужен препроцессор. Поэтому первым шагом является использование #define
вместо перечисления.
Но из-за последовательности развертывания макросов вторым шагом является использование промежуточного макроса.
#define TEST_M2(_spn) struct astruct _test_struct_##_spn = { .spn = _spn, }; #define TEST_M(_spn) TEST_M2(_spn) #define SPN_1 18 struct astruct { int spn; }; TEST_X(SPN_1) TEST_X(18)
Это также работает с буквенными числами.
С помощью GCC вы можете проверить полученный источник, если используете его опцию «-E».