Well, it seems that a struct with consecutive bitfields gets compacted and when is passed to printf
with the %d
format specifier, this manifests like some kind of "bit aggregation" (see Note). After some testing with different values and such, I came up with the following scheme :
The struct members (bitfields) are aligned thusly:
n n n n n m m m
ie in "descending" order - last comes first.
Then, in main
, b.m gets the value 2 which in binary is 10 and in 3-digit format is 010, and b.n gets the value 6 which in binary is 110 and in 5-digit format is 00110, so you end up with 00110010 which has a dec value of ... 50.
To further test this hypothesis I expanded the b struct with one more member and checked if it still holds:
#include <stdio.h>
struct {
unsigned m : 3;
unsigned n : 5;
unsigned o : 5;
} b;
int main(void) {
b.m = 1;
b.n = 1;
b.o = 1;
printf("%d\n",b);
return 0;
}
According to the hypothesis the struct members should be aligned this way:
o o o o o n n n n n m m m
and with the values assigned to them in main
(ie 1, 1 and 1) this should result to the binary 0000100001001 which in dec is 265.
Compiling and running yields:
$ gcc -Wall -o stprint stprint.c
stprint.c: In function ‘main’:
stprint.c:13:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘struct <anonymous>’ [-Wformat=]
printf("%d\n",b);
^
$ ./stprint
265
ie a result that (most probably) verifies the hypothesis.
Hope I shed some light on this behavior.
Edit/Note: In case it is not clear from the above, as other commenters pointed out, this behavior depends on the implementation, meaning that it is up to the compiler to decide if this "bit aggregation" takes place or not, and what is the specific order. One has also to take into account the endianness of the underlying platform (see here for example) For this post gcc version 4.8.4
was used in a Ubuntu system.