Campi di bit C
Oltre ai dichiaratori per i membri di una struttura o di un'unione, un dichiaratore di struttura può anche essere un numero specificato di bit, denominato "campo di bit". La sua lunghezza viene impostata dall'dichiaratore per il nome del campo da due punti. Un campo di bit viene interpretato come un tipo integrale.
Sintassi
struct-declarator
:
declarator
type-specifier
declarator
optare :
constant-expression
constant-expression
Specifica la larghezza del campo in bit. L'oggetto type-specifier
declarator
per deve essere unsigned int
, signed int
o int
e deve constant-expression
essere un valore intero non negativo. Se il valore è zero, la dichiarazione non ha un elemento declarator
. Non sono consentite matrici di campi di bit, puntatori a campi di bit e funzioni che restituiscono campi di bit. L'elemento declarator
facoltativo assegna il nome al campo di bit. I campi di bit possono essere dichiarati come parte di una struttura. L'operatore address-of (&
) non può essere applicato ai componenti del campo di bit.
Non è possibile fare riferimento ai campi di bit senza nome e il relativo contenuto in fase di esecuzione è imprevedibile. I campi di bit possono essere utilizzati come campi fittizi per scopi di allineamento. Un campo di bit senza nome la cui lunghezza specificata è 0 garantisce che l'archiviazione per il membro successivo in struct-declaration-list inizi su un limite int
.
Il numero di bit in un campo di bit deve essere minore o uguale alla dimensione del tipo sottostante. Ad esempio, queste due istruzioni non sono legali:
short a:17; /* Illegal! */
int long y:33; /* Illegal! */
Questo esempio definisce una matrice bidimensionale di strutture denominata screen
.
struct
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];
La matrice contiene 2.000 elementi. Ogni elemento è un struttura individuale contenente quattro membri di tipo campo di bit: icon
, color
, underline
e blink
. La dimensione di ogni struttura è di 2 byte.
I campi di bit hanno la stessa semantica dei tipi interi. Un campo di bit viene usato nelle espressioni esattamente come una variabile dello stesso tipo di base. Non importa quanti bit si trovano nel campo di bit.
Sezione specifica Microsoft
I campi di bit definiti come int
vengono considerati come signed
. Un'estensione Microsoft allo standard ANSI C consente char
i tipi e long
(entrambi signed
e unsigned
) per i campi di bit. I campi di bit senza nome con tipo base long
, short
o (signed
o unsigned
char
) forzano l'allineamento a un limite appropriato al tipo di base.
I campi di bit sono allocati in un Integer dal bit meno significativo a quello più significativo. Nel codice riportato di seguito
struct mybitfields
{
unsigned short a : 4;
unsigned short b : 5;
unsigned short c : 7;
} test;
int main( void )
{
test.a = 2;
test.b = 31;
test.c = 0;
return 0;
}
i bit di test
verrebbero disposti nel modo seguente:
00000001 11110010
cccccccb bbbbaaaa
Poiché la famiglia di processori 8086 archivia il byte basso di valori integer prima del byte elevato, l'intero 0x01F2
verrebbe archiviato nella memoria fisica come 0xF2
seguito da 0x01
.
Lo standard ISO C99 consente a un'implementazione di scegliere se un campo di bit può allontanarsi tra due istanze di archiviazione. Si consideri questa struttura, che archivia i campi di bit che totali di 64 bit:
struct
{
unsigned int first : 9;
unsigned int second : 7;
unsigned int may_straddle : 30;
unsigned int last : 18;
} tricky_bits;
Un'implementazione C standard potrebbe comprimere questi campi di bit in due interi a 32 bit. Potrebbe archiviare tricky_bits.may_straddle
come 16 bit in un intero a 32 bit e 14 bit nell'intero a 32 bit successivo. La convenzione di Windows ABI raggruppa i campi di bit in numeri interi di archiviazione singoli e non raggruppa le unità di archiviazione. Il compilatore Microsoft archivia ogni campo di bit nell'esempio precedente in modo che si adatti completamente a un intero a 32 bit. In questo caso, first
e second
vengono archiviati in un intero, may_straddle
vengono archiviati in un secondo intero e last
vengono archiviati in un terzo intero. L'operatore sizeof
restituisce 12
in un'istanza di tricky_bits
. Per altre informazioni, vedere Riempimento e allineamento dei membri della struttura.
Fine sezione specifica Microsoft