2013-09-21 8 views
1

Зачем нужен этот кусок кода?Размер ограничивающих структур с использованием:

typedef struct corr_id_{ 
    unsigned int size:8;  
    unsigned int valueType:8; 
    unsigned int classId:8; 
    unsigned int reserved:8;  

} CorrId; 

Я провел некоторое исследование вокруг него и обнаружил, что таким образом мы ограничиваем потребление памяти только тем, что нам нужно. .

typedef struct corr_id_new{ 
    unsigned int size;  
    unsigned int valueType; 
    unsigned int classId; 
    unsigned int reserved; 

} CorrId_NEW; 

typedef struct corr_id_{ 
    unsigned int size:8;  
    unsigned int valueType:8; 
    unsigned int classId:8; 
    unsigned int reserved:8; 

} CorrId; 

int main(){ 
CorrId_NEW Obj1; 
CorrId  Obj2; 

std::cout<<sizeof(Obj1)<<endl; 
std::cout<<sizeof(Obj2)<<endl; 
} 

Выход: -

16 
4 

Я хочу, чтобы понять реальный случай использования таких сценариев? почему мы не можем объявить структуру что-то вроде этого,

typedef struct corr_id_new{ 
    unsigned _int8 size;  
    unsigned _int8 valueType; 
    unsigned _int8 classId; 
    unsigned _int8 reserved; 

} CorrId_NEW; 

Связано ли это с оптимизацией компилятора? Или, каковы преимущества объявления структуры таким образом?

+0

На самом деле вы должны объединить два подхода ... или использовать 'pack' /' packed' –

+2

Вы уверены, что вывод '4 16', а не' 16 4'? –

+0

Спасибо. внесли эти изменения. –

ответ

1

Давайте посмотрим простой сценарий,

typedef struct student{ 
    unsigned int age:8; // max 8-bits is enough to store a students's age 255 years 
    unsigned int roll_no:16; //max roll_no can be 2^16, which long enough 
    unsigned int classId:4; //class ID can be 4-bits long (0-15), as per need. 
    unsigned int reserved:4; // reserved 

}; 

Над случае вся работа выполняется только в 32-бит.

Но если вы используете только целое число, это заняло бы 4 * 32 бит.

Если мы возьмем возраст как 32-битное целое число, оно может храниться в диапазоне от 0 до 2^32. Но не забывайте, что возраст нормального человека - это всего лишь 100 или 140 или 150 (даже кто-то, кто учится в этом возрасте также), которому нужно хранить максимум 8 бит, поэтому зачем тратить оставшиеся 24 бита.

+0

+20 для вашего ответа .. :) –

1

Это часто используется для создания pragma pack битовых полей с этикетками, например .:

#pragma pack(0) 

struct eg { 
    unsigned int one : 4; 
    unsigned int two : 8; 
    unsigned int three : 16 
}; 

Может быть отлит для любой цели на int32_t, и наоборот. Это может быть полезно при чтении сериализованных данных, следующих за протоколом (языковой агностик) - вы извлекаете int и передаете его в struct eg для соответствия полям и размерам полей, определенным в протоколе. Вы также можете пропустить преобразование и просто прочитать кусок размера int в такой структуре, указывая, что размеры битового поля соответствуют размерам полей протокола. Это чрезвычайно распространено в сетевом программировании - если вы хотите отправить пакет по протоколу, вы просто заполняете свою структуру, сериализуете и передаете.

Отметьте, что pragma pack не является стандартным C, но он распознается различными распространенными компиляторами. Однако без пакета pragma компилятор может свободно размещать промежутки между полями, уменьшая значение использования для целей, описанных выше.

2

Я хочу понять реальный вариант использования таких сценариев?

Например, структура регистра состояния некоторого CPU может выглядеть следующим образом:

enter image description here

Для того, чтобы представить его через структуру, можно использовать битовое:

struct CSR 
{ 
    unsigned N: 1; 
    unsigned Z: 1; 
    unsigned C: 1; 
    unsigned V: 1; 
    unsigned : 20; 
    unsigned I: 1; 
    unsigned : 2; 
    unsigned M: 5; 
}; 

Здесь вы можете видеть, что поля не умножаются на 8, поэтому вы не можете использовать int8_t или что-то подобное.

1

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

Основная цель :8 нотации разрешить использование дробных байт, как в

struct foo { 
    uint32_t a:1; 
    uint32_t b:2; 
    uint32_t c:3; 
    uint32_t d:4; 
    uint32_t e:5; 
    uint32_t f:6; 
    uint32_t g:7; 
    uint32_t h:4; 
} 

Чтобы минимизировать отступы, я настоятельно рекомендую, чтобы узнать отступы правила самостоятельно, они не трудно понять. Если вы это сделаете, вы можете знать, что ваша версия с unsigned _int8 не добавляет любой прокладка. Или, если вам не нравится изучать эти правила, просто используйте __attribute__((__packed__)) в своей структуре, но это может привести к серьезному снижению производительности.

Смежные вопросы