Битовые поля в C со структурой, содержащей объединение структур - PullRequest
3 голосов
/ 20 февраля 2011

Хм ... почему, когда я печатаю 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 ]

13 голосов
/ 20 февраля 2011

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

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  

edit: Чтобы уточнить, основываясь на комментариях ниже:

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

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

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

0 голосов
/ 26 августа 2011

Добавление к ответу, данному @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;
  // ...
};

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

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

...