Битовые поля в C со структурой, содержащей объединение структур

Хм... почему, когда я печатаю sizeof(struct MyStruct), это выводит 3 (вместо 2) для этого кода?

#pragma pack(push, 1)
    struct MyStruct
    {
        unsigned char a : 6;
        union
        {
            struct
            {
                unsigned int b : 9;
            };
        };
    };
#pragma pack(pop)

В случае, если это важно, я запускаю MinGW GCC 4.5.0 на Windows 7 x64, но, честно говоря, результат для меня достаточно странный, так что я не думаю, что компилятор и ОС здесь имеют большое значение.:\

2 ответа

Решение

Вы не можете иметь поле, начинающееся с адреса, который не выровнен по байту. Вы ожидаете:

6 bits + 9 bits -> 15 bits -> 2 bytes

но то, что вы получаете:

6 bits -> 1 byte
9 bits -> 2 bytes
total ->  3 bytes

Данные хранятся как:

| 1 byte | 2 byte |3 byte | 
 aaaaaaXX bbbbbbbb bXXXXX  

когда вы ожидали:

| 1 byte | 2 byte |
 aaaaaabb bbbbbbbX  

изменить: уточнить на основе комментариев ниже:

Объединение (и содержащая структура) должны быть выровнены по байту. Неважно, что содержимое - только 9 бит, само объединение / структура - полные 16 бит. Обратите внимание, что вы не можете сделать следующее:

struct MyStruct
{
    unsigned char a : 6;
    union
    {
        struct
        {
            unsigned int b : 9;
        } c:9;
    } d:9;
};

Поскольку C не позволит вам указать битовый размер всей структуры.

В дополнение к ответу @nss - мои извинения, это был бы комментарий, если бы комментарии не были так ограничены форматированием:

#include <stdlib.h>

struct Test {
  unsigned short x : 6;
  unsigned short y : 1;
  unsigned short z;
};

int main( int argc, char *argv[] ) {
  printf( "sizeof( Test ) = %d\n", sizeof( struct Test ) );

  return 0;
}

Он печатает "4" для размера. Я тестировал с gcc, g++ и Sun Studio CC и cc.

Не то чтобы я рекомендовал делать то, что вы пытаетесь сделать, но вы, вероятно, могли бы сделать то, что вы пытаетесь сделать с профсоюзом. Я видел (но не написал сам) код, который выглядел так:

struct Test {
  unsigned short x1 : 6;
  unsigned short x2 : 3;
                    : 1; // unused
  unsigned short x3 : 4;
  // ...
};

У меня там может быть немного неправильный синтаксис... но я так не думаю.

Суть в том, что: создайте две отдельные структуры (или структуру и объединение) с макетом, который вы собирались, затем вставьте несколько фиктивных элементов, где они должны перекрываться, и объедините их вместе.

Другие вопросы по тегам