Hi every one the problem is that i have in this macro
#define ADD_COMP(s1,s2,type)({\
int _x=0;\
for(int i=0;i<n_addrs;i++){\
if(memcmp(s1,&(s2->##type),6)!=0){\
_x=-1;\
}else{\
break;\
}\
}\
_x;\
})
s1 is a simple array and s2 is a structure with 4 vectors as members like this
typedef struct example{
char[6] one,
char[6] two,
char[6] three
}example;
Now for own reason i need to create a function that compares the s1 array of size 6 bytes with only a member of example, so for this purpose i wrote ADD_CMP using ## operator to be more generic as possible So i defined:
#define one
#define two
#define three
and i used the function different times in this way hoping in the succes of macros expansion
ADD_COMP(some_array,example1,one)
ADD_COMP(some_array,example1,two)
ADD_COMP(some_array,example1,three)
but the compiler return as error:
error: pasting "->" and "one" does not give a valid preprocessing token
error: pasting "->" and "two" does not give a valid preprocessing token
error: pasting "->" and "three" does not give a valid preprocessing token
How can i fix it without write the same function for every structure member?
As the error suggests, there never was need for ##
, as it is used to paste two preprocessing tokens to form a single one.
#define VAR(name, num) name##num
int VAR(foo, 1); // foo and 1 must be pasted together as foo1, instead of foo 1
The macro should compile with fixes to several syntax errors and missing declarations
#include<stdlib.h>
#include<string.h>
int n_addrs = 6;
#define ADD_COMP(s1,s2,type) {\
int _x=0;\
for(int i=0;i<n_addrs;i++){\
if(memcmp(s1,&(s2->type),6)!=0){\
_x=-1;\
}else{\
break;\
}\
}\
_x;\
}
typedef struct example{
char one[6];
char two[6];
char three[6];
}example;
void foo(void)
{
example* example1 = malloc(sizeof(example));
char some_array[6];
ADD_COMP(some_array,example1,one)
ADD_COMP(some_array,example1,two)
ADD_COMP(some_array,example1,three)
}
Note a compound statement { ... }
isn't an expression and can not be used as such. By adding extra parentheses around it, you are using gnu's extension and is not standard C.
You should instead, just write a function to do this instead. You will then be able to return _x
and with modern optimizers, there should be negligible to non-existant overhead.
The token pasting operator is designed for cases where you want to glue two different preprocessor tokens into a single token. For example, you might write something like
#define Glue(x) x my##x_
and then write
Glue(int);
to get this variable declaration:
int my_int;
Here, token-pasting combined the token “my_” with the token “int” to form the new token “my_int,” a new single token representing a name.
Once you paste two tokens together, the preprocessor doesn’t rescan them to figure out whether it’s a compound of several different individual tokens. It treats whatever is formed as a single token. For example, this code won’t compile:
#define BadAdd(x, y) x##+##y
int z = BadAdd(137, 42);
The issue here is that the token pasting forms a single preprocessing token 137+42
. The preprocessor then tries to map this preprocessing token to a single logical token, but there’s no single token that this could correspond to. Normally, C or C++ would treat this as three separate tokens (137, +, and 42), but since you’ve forcibly glued them together the compiler has no idea what it’s looking at.
Contrast this with a more traditional Add macro, which for the purposes of exposition omits tons of important parentheses:
#define Add(x, y) x + y
int z = Add(137, 42);
Here, Add(137, 42) expands out to a sequence of three tokens (137, +, 42), which the compiler in a later phase can then interpret as an addition expression.
The macro you wrote above is like the BadAdd macro. By gluing the -> token together with a field name, you end up with a single unit like ->one
that the compiler can’t meaningfully interpret as a single token. Just delete the ## here - just like going from BadAdd to Add, this will generate a sequence of tokens rather than a single token, which is what you want here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With