Cosa significa C ++ struct syntax “a: b” mean

Se ho una struttura C ++, definendo una parola di dati a 64 bit come ..

struct SMyDataWord { int Name : 40; int Colour : 24; }; 

Che cosa significa la syntax : 40 … significa che i primi 40 bit sono riservati per il nome e i restanti 24 bit per il colore?

È così che sembra essere usato, ma non l’ho mai incontrato prima.

Campi bit, riportati da C. Il Name è largo 40 bit, il Colour è largo 24 bit. La tua struct ha quindi almeno 64 bit. Sul mio sistema 64 bit sarebbero 8 byte.

Sì, questa è la syntax per i bitfield . Sono comunemente usati per definire le strutture che si associano ai registri hardware. Ci sono alcune cose da tenere a mente se si decide di usarle, una è che non si può sapere come il compilatore fa il layout, l’ordine e il padding nei byte effettivi che compongono i campi possono e differiranno tra i compilatori (e forse con lo stesso compilatore ma con diverse impostazioni di ottimizzazione, anche).

Questa è una definizione bitfield.

Il nome è un numero intero che è in grado di memorizzare esattamente 40 bit di informazioni. Il colore può memorizzare 24 bit.

Questo è spesso fatto per risparmiare spazio nelle strutture spesso necessarie, o comprimere il codice in una dimensione che è facile da gestire per la CPU (nel tuo caso 64 bit. Adatta esattamente in un registro CPU su una macchina a 64 bit).

Il codice che accede ai bitfield verrà eseguito un po ‘più lentamente però.

Usali con giudizio :

Ricorda che quasi tutto ciò che riguarda i campi bit dipende dall’implementazione. Ad esempio, se i bit sono memorizzati da sinistra a destra o da destra a sinistra dipende dalla reale architettura dell’hardware. Inoltre, ogni compilatore utilizza un modello di allineamento dei membri diverso, motivo per cui la dimensione del BillingRec ottimizzato è 12 byte anziché 9. Non è ansible prendere l’indirizzo di un campo bit né creare matrici di bit. Infine, sulla maggior parte delle implementazioni l’uso dei campi bit comporta un sovraccarico di velocità. Pertanto, quando si ottimizza il codice, misurare l’effetto di una determinata ottimizzazione e i relativi compromessi prima di decidere di utilizzarlo.

Qui sizeof dimostra sizeof cosa sta succedendo sotto il cofano:

 #include  #include  struct bc_1 { int a : 1; int b : 1; }; struct bc_2 { int a : 31; int b : 1; }; struct bc_3 { int a : 32; int b : 1; }; struct bc_4 { int a : 31; int b : 2; }; struct bc_5 { int a : 32; int b : 32; }; struct bc_6 { int a : 40; int b : 32; }; struct bc_7 { int a : 63; int b : 1; }; int main(int argc, char * argv[]) { std::cout << "CHAR_BIT = " << CHAR_BIT; std::cout << " => sizeof(int) = " << sizeof(int) << std::endl; std::cout << "1, 1: " << sizeof(struct bc_1) << std::endl; std::cout << "31, 1: " << sizeof(struct bc_2) << std::endl; std::cout << "32, 1: " << sizeof(struct bc_3) << std::endl; std::cout << "31, 2: " << sizeof(struct bc_4) << std::endl; std::cout << "32, 32: " << sizeof(struct bc_5) << std::endl; std::cout << "40, 32: " << sizeof(struct bc_6) << std::endl; std::cout << "63, 1: " << sizeof(struct bc_7) << std::endl; } 

Ciò che segue dipende dal tuo compilatore e dal tuo sistema operativo, e possibilmente dal tuo hardware. Su macOS con gcc-7 (con un CHAR_BIT = 8, un int a 32 bit (cioè metà di 64 bit di long ) ha sizeof(int) = 4) questo è l'output che vedo:

 CHAR_BIT = 8 => sizeof(int) = 4 1, 1: 4 31, 1: 4 32, 1: 8 31, 2: 8 32, 32: 8 40, 32: 12 63, 1: 8 

Questo ci dice diverse cose: se entrambi i campi di tipo int adattano a un singolo int (cioè 32 bit nell'esempio sopra), il compilatore alloca solo il valore di memoria di un singolo int ( bc_1 e bc_2 ). Una volta, un singolo int non può più tenere i bitfield, aggiungiamo un secondo ( bc_3 e bc_4 ). Si noti che bc_5 è a capacità.

È interessante notare che possiamo "selezionare" più bit di quelli consentiti. Vedi bc_6 . Qui g ++ - 7 dà un avvertimento:

 bitfields.cpp::30:13: warning: width of 'bc_6::a' exceeds its type int a : 40; ^~ 

Si noti che: clang ++ lo spiega in modo più dettagliato

 bitfields.cpp:30:9: warning: width of bit-field 'a' (40 bits) exceeds the width of its type; value will be truncated to 32 bits [-Wbitfield-width] int a : 40; ^ 

Tuttavia sembra che sotto il cofano, il compilatore alloca un altro valore int di memoria. O per lo meno, determina la dimensione corretta. Immagino che il compilatore ci int a = bc_6::a non accedere a questa memoria come int a = bc_6::a (scommetterei che int a avrebbe quindi solo i primi 32 bit di campo bc_6::a ...). Ciò è confermato da bc_7 cui dimensione totale è quella di due int , ma il primo campo copre la maggior parte di essi.

Infine, la sostituzione di int con long nell'esempio precedente si comporta come previsto:

 CHAR_BIT = 8 => sizeof(long) = 8 1, 1: 8 31, 1: 8 32, 1: 8 31, 2: 8 32, 32: 8 40, 32: 16 63, 1: 8