Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C11 _Generic() - How can I suppress gcc code evaluation (Error check) for selections which are not matching with selector

Tags:

c

gcc

c11

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?

like image 857
Hardik Panchal Avatar asked Oct 25 '25 08:10

Hardik Panchal


1 Answers

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.

like image 66
Lundin Avatar answered Oct 27 '25 22:10

Lundin



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!