https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92684
Bug ID: 92684 Summary: bitfield behavior not matching the declared type Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: wuxb45 at gmail dot com Target Milestone: --- found wrong data when compiled by gcc 9.2.0 (x86_64, -std=gnu11). Have not tried other gcc versions. The results are correct on clang 8.0.1. Long story short: some bits are missing when using bitfields with uint64_t as the declared type. Maybe I should use a (u64) cast on every dereference to those fields. But the results are not always wrong. Maybe I should read some C11 specs. But consider the different behaviors between gcc and clang, I decide to report a bug here in hope to get some better help. Thanks. This reproduces the results: gcc/clang -std=gnu11 main.c #include <stdint.h> #include <stdlib.h> #include <stdio.h> typedef uint64_t u64; struct st { union { struct { u64 v1:19; u64 v2:45; }; void * ptr; }; }; struct bits { u64 bit1:1; u64 bitx:63; }; int main(void) { char * val = "0xffff0000fff8"; // x has 48 valid bits, the three low bits are 0s volatile u64 x = strtoull(val, NULL, 16); printf("%lx\n", x); // st stores that 45 bits struct st st = {.v1 = 0, .v2 = (x >> 3)}; printf("%p\n", st.ptr); // y should get the original bits; but the three high bits are gone. u64 y = st.v2 << 3; printf("%lx\n", y); // this is another (minor) related case. // some are correct and some are wrong. struct bits b = {.bit1 = 1, .bitx = 0}; // this is more interesting. gcc shows "80000000", clang shows "1" printf("%lx %lx %lx\n", b.bit1, b.bit1 << 1, b.bit1 << 63); return 0; }