I have a struct with a union and an enum of its kind in it. I've made a macro that outputs a compound literal of the struct, that sets the kind and the data of the union according to the type passed to the macro use _Generic.
Example code:
#include <stdio.h>struct mystruct { enum { K_NUM, K_STR } kind; union { int num; char * str; };};#define MYSTRUCT(X) _Generic((X), \ int: (struct mystruct){K_NUM, .num=X}, \ char *: (struct mystruct){K_STR, .str=X} \)void print_mystruct(struct mystruct s) { switch (s.kind) { case K_NUM: printf("mystruct (num): %d\n", s.num); break; case K_STR: printf("mystruct (str): %s\n", s.str); break; }}int main() { print_mystruct(MYSTRUCT(2)); print_mystruct(MYSTRUCT("test"));}
It does compile with gcc, and then running it correctly outputs:
mystruct (num): 2mystruct (str): test
But I get all these compile warnings:
c.c: In function 'main':c.c:21:26: warning: initialization of 'char *' from 'int' makes pointer from integer without a cast [-Wint-conversion] 21 | print_mystruct(MYSTRUCT(2)); | ^c.c:10:40: note: in definition of macro 'MYSTRUCT' 10 | char *: (struct mystruct){K_STR, .str=X} \ | ^c.c:21:26: note: (near initialization for '(anonymous).<anonymous>.str') 21 | print_mystruct(MYSTRUCT(2)); | ^c.c:10:40: note: in definition of macro 'MYSTRUCT' 10 | char *: (struct mystruct){K_STR, .str=X} \ | ^c.c:22:26: warning: initialization of 'int' from 'char *' makes integer from pointer without a cast [-Wint-conversion] 22 | print_mystruct(MYSTRUCT("test")); | ^~~~~~c.c:9:37: note: in definition of macro 'MYSTRUCT' 9 | int: (struct mystruct){K_NUM, .num=X}, \ | ^c.c:22:26: note: (near initialization for '(anonymous).<anonymous>.num') 22 | print_mystruct(MYSTRUCT("test")); | ^~~~~~c.c:9:37: note: in definition of macro 'MYSTRUCT' 9 | int: (struct mystruct){K_NUM, .num=X}, \ | ^
I tried casts in the compound literals like so:
int: (struct mystruct){K_NUM, .num=(int)X}, \char *: (struct mystruct){K_STR, .str=(char *)X} \
But I get different warnings:
c.c: In function 'main':c.c:9:37: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] 9 | int: (struct mystruct){K_NUM, .num=(int)X}, \ | ^c.c:22:17: note: in expansion of macro 'MYSTRUCT' 22 | print_mystruct(MYSTRUCT("test")); | ^~~~~~~~