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?
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.
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.
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;
}