P.S.- I have taken int and int * for simplicity purpose, It can also be struct and struct *.
I am trying to implement a macro to copy data present in one variable to other independent of the variable datatype, In the below solution I am using '_Generic' compiler feature. program 1:
#include<stdio.h>
#include <string.h>
#define copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void *)&var,sizeof(int));}),\
int *:({memcpy(newVar,(void *)var,sizeof(int));}),default:newVar=var)
int main() {
int data = 2;
int *copy;copy = (int *)malloc(sizeof(int));
copyVar(data,copy);
printf("copied Data=%i",*copy);
}
Program 2:
#include<stdio.h>
#include <string.h>
#define copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void *)&var,sizeof(int));}),\
int *:({memcpy(newVar,(void *)var,sizeof(int));}),default:newVar=var)
int main() {
int data = 2;
int *copy;copy = (int *)malloc(sizeof(int));
copyVar(&data,copy);
printf("copied Data=%i",*copy);
}
Now problem is, 'program 1' get compiled successfully despite some warning. But while compiling program 2 gcc throwing error:
error: lvalue required as unary '&' operand #define copyVar(var,newVar) _Generic((var),int:({memcpy(newVar,(void *)&var,sizeof(int));}),
and I assume this is due to since _Generic int: selection get preprocessed with one more ampersand
(void *)&&var
why is gcc evaluates all selection?
Your code has various problems: you copy data into an uninitialized pointed, you have superfluous void* casts, you treat _Generic as some sort of compound statement instead of an expression, and so on.
But to answer your question, your code doesn't work because the result of &something is not a lvalue. Since the & operator needs a lvalue, you cannot do & &something. (And you cannot do &&something either because that gets treated as the && operator by the "maximum munch rule".)
So your code doesn't work for the same reason as this code doesn't work:
int x;
int**p = & &x;
gcc tells you that &x is not a lvalue:
lvalue required as unary '&' operand
EDIT - clarification
This _Generic macro, like any macro, works like pre-processor text replacement. So when you have this code in the macro:
_Generic((var), ...
int: ... (void *)&var
int*: ... (void)var
It gets pre-processed as
_Generic((&data), ...
int: ... (void *)& &data
int*: ... (void)&data
And all paths of the _Generic expression are pre-processed. _Generic itself is not part of the pre-processor, but gets evaluated later on, like any expression containing operators. The whole expression is checked for syntactic correctness, even though only one part of the expression is evaluated and executed.
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