Как присвоить значение внутри моего макроса?
Я пытаюсь присвоить значение внутри моего x-макроса, но я не совсем понимаю, почему оно не работает:
#include <stdio.h>
typedef struct
{
int a;
int b;
} struct_t;
#define MY_LIST \
MY_ELEMENT(a) \
MY_ELEMENT(b)
#define MY_ELEMENT(x) struct_t x; \
x.a=33;
MY_LIST
#undef MY_ELEMENT
int main(void)
{
fprintf(stdout, "a: %d\n", a.a);
return 0;
}
При компиляции я получаю следующую ошибку:
test.c:14:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘.’ token
x.a=33;
Может кто-нибудь объяснить, почему я получаю эту ошибку и как ее решить?
3 ответа
Вы должны посмотреть на предварительно обработанную форму вашего кода в исходном файле slethoprod.c
, С GCC вы можете получить его с gcc -C -E slethoprod.c > slethoprod.i
затем проверьте (с помощью редактора или пейджера), что slethoprod.i
файл.
Он содержит такие вещи, как:
struct_t a; a.a = 33; struct_t b; b.a = 33;
что, очевидно, является недопустимым кодом C (поскольку он имеет некоторое присваивание вне какой-либо функции в области видимости файла; помните, что инициализация в объявлении не является присваиванием).
Вы могли бы хотеть иметь некоторое определение (с инициализацией), такое как
struct_t a = {33};
или даже (для удобства чтения) инициализация структуры, например
struct_t b = {.a=33};
и вы могли бы сыграть причудливые приемы препроцессора, чтобы получить это.
Загляните на какой-нибудь справочный сайт C и / или изучите стандарт C11 n1570, чтобы узнать больше о C. Прочитайте также документацию вашего компилятора (например, GCC) и вашего препроцессора (например, cpp).
Кстати, я лично чувствую, что называя глобал с таким же именем a
поскольку некоторые поля в нем имеют плохой вкус (даже если это допустимо, поскольку имена полей и глобальные переменные имеют разные пространства имен). Для удобства чтения я рекомендую избегать этого.
Присвоение значений структурным полям вне области действия функции не подходит, поэтому ваш исходный код не работает
#define MY_ELEMENT(x) struct_t x; \
x.a=33;
MY_LIST //<-- Inaproppriate
#undef MY_ELEMENT
Если вы хотите использовать текущий макрос, вы должны написать так:
#include <stdio.h>
typedef struct
{
int a;
int b;
} struct_t;
#define MY_LIST \
MY_ELEMENT(a) \
MY_ELEMENT(b)
#define MY_ELEMENT(x) struct_t x; \
x.a=33;
int main(void)
{
MY_LIST;
fprintf(stdout, "a: %d\n", a.a);
return 0;
}
Или вы можете изменить свой макрос следующим образом: #define MY_ELEMENT(x) struct_t x = {33, 0};
или даже лучше это: #define MY_ELEMENT(x) struct_t x = {.a = 33};
и оставьте остальную часть своего кода как есть.
Таким образом, вы будете инициализировать вашу переменную прямо в макросе.
Ошибка, на которую вы ссылаетесь, в основном возникает, когда ;
отсутствует где-то в коде.
В этом случае, если вы добавите \
после x.a=33;
а затем позвоните MY_LIST
это уходит.
Но тогда вам следует позвонить MY_LIST
в функции для a
быть определенным в main
вот рабочая версия вашего кода
#include <stdio.h>
typedef struct
{
int a;
int b;
} struct_t;
#define MY_LIST \
MY_ELEMENT(a) \
MY_ELEMENT(b)
#define MY_ELEMENT(x) struct_t x; \
x.a=33;
int main(void)
{
MY_LIST;
fprintf(stdout, "a: %d\n", a.a);
return 0;
}