Почему без знака сопоставляется с 32 битами в MSVC С++?

У меня есть следующая структура, определенная в MSVC++ 2008:

struct{
 Uint16  XDD;
 unsigned XDD_UI:8;
 unsigned XDD_CR:8;
}byte;

При выполнении sizeof для приведенной выше структуры видно, что unsigned использует 32 бита для хранения данных.

  • Почему это как-то связано с выравниванием памяти?
  • И как я могу заставить компилятор использовать только 8 бит, как определено, не касаясь определения структуры?

person drcelus    schedule 25.02.2014    source источник
comment
не могли бы вы опубликовать код, как вы проверяете, что XDD занимает 32 бита?   -  person Ivaylo Strandjev    schedule 25.02.2014
comment
Вы можете найти некоторую информацию, касающуюся упаковки битовых полей с помощью Visual-C++, здесь: randomascii.wordpress.com/2010/06/06/   -  person manlio    schedule 25.02.2014


Ответы (3)


Когда вы пишете unsigned, это сокращение от unsigned int, которое в Windows имеет ширину 32 бита. Это означает, что он имеет выравнивание 4. И поскольку ваша структура выровнена, между XDD и XDD_UI есть два байта заполнения и два байта заполнения в конце структуры.

Ваша структура выложена следующим образом:

0-1  XDD
2-3  <padding>
4-4  XDD_UI
5-5  XDD_CR
6-7  <padding>

Если вы хотите, чтобы структура была упакована, вам нужно ее упаковать. Используйте #pragma pack для достижения этого. Однако, даже если вы это сделаете, компилятор создаст структуру размером 6. Это потому, что битовые поля упакованы в unsigned int, и поэтому ваши два битовых поля всегда будут занимать 4 байта.

Если бы вы убедились, что ваши битовые поля были объявлены как имеющие тип, размер которого не превышает 2 байта, тогда ваша структура будет иметь размер 4 байта. И это было бы верно для выровненной структуры. Например, эта структура имеет размер 4.

struct s {
    unsigned short XDD;
    unsigned short XDD_UI:8;
    unsigned short XDD_CR:8;
};

Однако мне кажется более разумным объявить вашу структуру без битовых полей:

struct s {
    Uint16 XDD;
    unsigned char XDD_UI;
    unsigned char XDD_CR;
};

Вы можете объявить эту структуру выровненной и иметь желаемый макет.

person David Heffernan    schedule 25.02.2014
comment
Существуют ли какие-либо полезные программы, которые могут гарантированно работать в любой соответствующей реализации в соответствии с правилами, установленными стандартом C, которые не будут гарантированно работать, если битовые поля могут быть распределены любым способом, который компилятор считает нужным? Я понимаю, каковы правила, но мне любопытно, почему компилятору не разрешено, например. предоставить средство упаковки четырех шестибитных полей в 3-байтовую структуру, если аппаратное обеспечение может справиться с этим прилично. - person supercat; 26.02.2014

And how could I force the compiler to use only 8 bits as defined without touching the struct definition 

Используйте #pragma

#pragma pack(1)
struct{
 Uint16  XDD;
 unsigned XDD_UI:8;
 unsigned XDD_CR:8;
}byte;
#pragma pack()
person Sakthi Kumar    schedule 25.02.2014
comment
При использовании #pragma pack(1) размер структуры все еще больше, чем ожидалось. - person drcelus; 25.02.2014

В зависимости от компилятора и машины unsigned может быть и 64-битным. Поскольку ранее процессоры были 32-битными, стало обычным делом использовать 32-битные значения для целых чисел. Но мы не должны всегда полагаться на int или unsigned для определения диапазона.

Символ или unsgined char - верный способ использовать 8 бит. Но внутренне компилятор мог внести коррективы, чтобы использовать его как 4 байта для обработки.

person AgA    schedule 25.02.2014
comment
Нет, char минимум 8 бит, так же как unsigned минимум 16 бит. - person MSalters; 25.02.2014
comment
Но sizeof char всегда равен 1 в C lang. - person AgA; 25.02.2014
comment
Верно, но CHAR_BIT не всегда равно 8. - person MSalters; 25.02.2014