C Макрос получает значение токена вместо имени токена

#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».