Как присвоить значение внутри моего макроса? - PullRequest
0 голосов
/ 12 января 2019

Я пытаюсь присвоить значение внутри моего 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 ]

0 голосов
/ 12 января 2019

Ошибка, на которую вы ссылаетесь, в основном возникает, когда в коде отсутствует ;.
В этом случае, если вы добавите \ после 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;
}
0 голосов
/ 12 января 2019

Назначение значений для структурных полей вне области действия функции не подходит, поэтому ваш исходный код не работает

#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};

и оставьте остальной код как есть.

Таким образом, вы инициализируете переменную прямо в макросе.

0 голосов
/ 12 января 2019

Вам нужно просмотреть предварительно обработанную форму вашего кода в исходном файле 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 (поскольку он имеет некоторое назначение вне какой-либо функции, в файле scope ; помните, что инициализация в объявлении не назначение ).

Возможно, вы захотите получить какое-то определение (с инициализацией), например

struct_t a = {33};

или даже (для удобства чтения) инициализация структуры как

struct_t b = {.a=33};

и вы можете сыграть в фантастический препроцессор трюки, чтобы получить это.

Просмотрите сайт C и / или изучите стандарт C11 n1570 , чтобы узнать больше о C. Прочитайте также документацию вашего компилятора (например, GCC * 1040). *) и вашего препроцессора (например, cpp ).

Кстати, я лично чувствую, что присвоение имени глобалу с таким же именем a как некоторому полю в нем имеет плохой вкус (даже если это допустимо, поскольку имена полей и глобальные переменные имеют разные пространства имен ) , Для удобства чтения я рекомендую избегать этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...