Две силы в игре - это порядок байтов и выравнивание.Похоже, ваш компьютер хранит данные в формате с прямым порядком байтов, то есть младший байт хранится по младшему адресу.Таким образом, ваш инициализатор был эффективен:
entry.fields.id = (0xef >> 1) & 0x7f;
entry.fields.age = (0xef >> 7) & 1;
entry.fields.index = 0xaced;
entry.fields.class = random stack data & 0xf;
entry.fields.reserved = random stack data & 0xf;
Поскольку entry.fields.index является uint16_t, для вставки байта заполнения или выравнивания требовалось, чтобы последовательность битовых полей была прервана.Ваши предыдущие поля (id, age) вызывали смещение для 16-битного типа, компилятор исправил это, и ваш '0xbe' исчез.
Если вы слегка измените свое определение:
struct {
unsigned id: 7, age:1, index :16, class:4, reserved:4;
} fields;
Вы можете увидеть что-то ближе к тому, что вы ожидали.Обратите внимание на удаление "uint32_t", это немного претенциозно для битовых полей;без вреда, просто уродливо читать.
В форме вашего оригинала вы предоставляете ограничения выравнивания для битовых полей: id, age, class, reserved не может охватывать 8-битную границу.Индекс не может охватывать 16-битную границу.Когда он доходит до точки выделения для индекса, он должен ввести 8-битное заполнение для соответствия ограничению выравнивания.
В более короткой форме я дал id, age, index, class, reserved не может пересечь 32-битную границу;то, что компилятор может вместить в одно слово.