I've tried you hack, but it doesn't work with "long bit fields". Also, I've run into another problem. Instead of using unsigned char for the bit field I changed it to a long unsigned int:33 and now I can't print it without a warning.
Here is my Makefile: CC = gcc O = 3 X = c STD = c11 CFLAGS = -m64 -Wall -std=$(STD) all: test test.o: test.c $(CC) -x $(X) -O$(O) $(CFLAGS) -o test.o -c test.c objdump -d test.o > test.txt test: test.o $(CC) $(CFLAGS) test.o -o test clean: rm -f test test.o test.txt Here is the test: #include <stdio.h> struct big_bit_fields { long unsigned int b33:33; } __attribute__((__packed__)); _Static_assert(sizeof(struct big_bit_fields) == 5, L"big_bit_fields is not 5 bytes"); #define type_to_str(__x) _Generic((0)?(__x):(__x), \ _Bool : "_Bool", \ char : "char", \ signed char : "unsigned char", \ unsigned char : "unsigned char", \ short int : "short int", \ unsigned short int: "unsigned short int", \ int : "int", \ unsigned int : "unsigned int", \ long int : "long int", \ long unsigned int : "long unsigned int", \ long long int : "long long int", \ long long unsigned int : "long long unsigned int", \ default : "unknown type") int main(void) { struct big_bit_fields bbf = { .b33 = 0x1FFFFFFFF }; printf("bbf.b33=0x%lx\n", bbf.b33); printf(" type=%s\n", type_to_str(bbf.b33)); printf(" <<1 =0x%016lx\n", bbf.b33 << 1); printf(" (ull)<<1 =0x%016lx\n", (long unsigned int)bbf.b33 << 1); return 0; } Here the compile and run: $ make clean ; make ; ./test rm -f test test.o test.txt gcc -x c -O3 -m64 -Wall -std=c11 -o test.o -c test.c test.c: In function ‘main’: test.c:44:10: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘long unsigned int:33’ [-Wformat=] printf("bbf.b33=0x%lx\n", bbf.b33); ^ test.c:46:10: warning: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 2 has type ‘long unsigned int:33’ [-Wformat=] printf(" <<1 =0x%016lx\n", bbf.b33 << 1); ^ objdump -d test.o > test.txt gcc -m64 -Wall -std=c11 test.o -o test bbf.b33=0x1ffffffff type=unknown type <<1 =0x00000001fffffffe (ull)<<1 =0x00000003fffffffe On Fri, Feb 19, 2016 at 1:35 PM, Martin Sebor <mse...@gmail.com> wrote: > On 02/19/2016 11:25 AM, Wink Saville wrote: >> >> I'm using gcc 5.3.0: >> >> $ gcc --version >> gcc (GCC) 5.3.0 >> Copyright (C) 2015 Free Software Foundation, Inc. >> This is free software; see the source for copying conditions. There is NO >> warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR >> PURPOSE. >> >> >> And I've tried to use _Generic to print the type of a bit field but >> the compiler fails with: >> >> $ make >> gcc -Wall -std=c11 -o test.o -c test.c >> test.c: In function ‘main’: >> test.c:8:35: error: ‘_Generic’ selector of type ‘unsigned char:2’ is >> not compatible with any association >> #define type_to_str(__x) _Generic((__x), \ >> ^ >> test.c:17:18: note: in expansion of macro ‘type_to_str’ >> printf("%s\n", type_to_str(b.f1)); >> ^ >> Makefile:7: recipe for target 'test.o' failed >> make: *** [test.o] Error 1 >> bash: ./test: No such file or directory >> >> >> The test program is: >> >> $ cat test.c >> #include <stdio.h> >> >> struct bits { >> unsigned char f0; >> unsigned char f1:2; >> }; >> >> #define type_to_str(__x) _Generic((__x), \ >> unsigned char : "unsigned char") >> >> int main(void) { >> struct bits b = { .f0 = 255, .f1 = 3 }; >> >> printf("%d\n", b.f0); >> printf("%s\n", type_to_str(b.f0)); >> printf("%d\n", b.f1); >> printf("%s\n", type_to_str(b.f1)); >> >> return 0; >> } >> > ... >> >> How do I create a type association for a bit field? > > > I suspect this falls under the set of issues that fall under bug > 65471 - type interpretation in _Generic. The C language rules > for _Generic aren't completely clear about what conversions are > to take place. It would be helpful if you could your test case > to the bug to make sure the bitfield case is considered when > the issue is discussed by the C committee. > > https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65471 > > The only idea for a workaround that comes to mind is to trick GCC > into forgetting that it's a bit-field. This hack seems to work: > > #define type_to_str(__x) _Generic((0)?(__x):(__x), \ > > Martin >