Защо unsigned се преобразува в 32 бита в MSVC C++?

Имам следната структура, дефинирана в 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, което е 32 бита широко в Windows. Това означава, че има подравняване на 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. Но не трябва да разчитаме на int или unsigned, за да определим винаги диапазона му.

Char или 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