C - How to assign a value inside my macro?

2019-07-17 14:50发布

问题:

I am trying to assign a value inside my x-macro, but I don't really understand why it is not working:

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

When compiling this I get the following error:

test.c:14:2: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or   ‘__attribute__’ before ‘.’ token
 x.a=33;

Could somebody explain why I am getting this error and how to solve this?

回答1:

You need to look into the preprocessed form of your code in your source file slethoprod.c. With GCC, you can get it with gcc -C -E slethoprod.c > slethoprod.i then inspect (with an editor or a pager) that slethoprod.i file.

It contains stuff like:

struct_t a; a.a = 33; struct_t b; b.a = 33;

which is obviously not valid C code (since it has some assignment outside of any function, at file scope; remember that an initialization in a declaration is not an assignment).

You might want to have some definition (with initialization) such as

struct_t a = {33};

or even (for readability purposes) a struct initialization like

struct_t b = {.a=33};

and you could play fancy preprocessor tricks to get that.

Look into some C reference site and/or study the C11 standard n1570 to learn more about C. Read also the documentation of your compiler (e.g. GCC) and of your preprocessor (e.g. cpp).

BTW, I personally feel that naming a global with the same name a as some field in it is poor taste (even if it is legal, since field names and global variables have different namespaces). For readability purposes, I recommend avoiding that.



回答2:

Assigning values to structure fields outside of function scope isn't appropriate, so your original code doesn't work

#define MY_ELEMENT(x) struct_t x; \ 
x.a=33;
MY_LIST //<-- Inaproppriate
#undef MY_ELEMENT

If you want to use current macro, you should write like this:

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

Or you can change your macro this way: #define MY_ELEMENT(x) struct_t x = {33, 0};

or even better this: #define MY_ELEMENT(x) struct_t x = {.a = 33};

and leave the rest of your code as is.

So that way you will initialize your variable right in macro.



回答3:

The error you are referring mainly happens when there is a ; missing somewhere in code.
In this case if you add \ after x.a=33; and then call MY_LIST it goes away.
But then you should call MY_LIST in function for a to be defined in main
here is a working version of your code

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


标签: c x-macros