2010-12-28 9 views
11

Sto scrivendo un'applicazione C++ per Windows XP/Vista/7 utilizzando Visual Studio 2008. Alcune delle mie strutture utilizzano un campo bit, come mostrato nell'esempio.Quale fine di un campo bit è il bit più significativo?

typedef struct myStruct_tag 
{ 
    BYTE myVar1; 
    WORD myVar2; 
    WORD myVar3; 
    union 
    { 
     struct 
     { 
      BYTE   :1; 
      BYTE field1 :1; 
      BYTE field2 :1; 
      BYTE reserved :5; 
     } myBitField; 
     BYTE myVar4; 
    }; 
    BYTE myVar5; 
    BYTE myVar6; 
} myStruct_t; 

Quale fine del campo è il bit più significativo?

+2

Nota: Secondo la norma, l'MSB non è definito. Sulla tua piattaforma specifica, sospetto che 'reserved' contenga l'MSB ma non sono positivo. –

+0

@Billy: sembra una risposta per me. –

+0

Ehm ... Questa è una domanda piuttosto strana. Hai solo 3 campi di bit nella tua dichiarazione. 2 di questi sono campi di bit a 1 bit, cioè non vi è alcun problema di "quale fine" con loro, poiché c'è solo 1 bit lì. L'unico campo di bit multi-bit chiamato 'reserved', che suggerisce che non è usato affatto. Quindi, fondamentalmente, l'unica domanda di campo che tu puoi applicare è 'riservata'. Stai chiedendo specificamente su 'reserved'? In caso contrario, chiarisci la tua domanda. – AnT

risposta

18

C99 norma 6.7.2.1/10 (enfasi mia):

L'attuazione può assegnare qualsiasi unità di memorizzazione indirizzabile abbastanza grande da contenere un campo di bit. Se rimane abbastanza spazio, un campo di bit che segue immediatamente un altro campo di bit in una struttura deve essere impacchettato in bit adiacenti della stessa unità. Se lo spazio insufficiente rimane, se un campo di bit che non si adatta viene inserito nell'unità successiva o si sovrappone alle unità adiacenti è definito dall'implementazione. L'ordine di assegnazione dei campi di bit all'interno di un'unità (ordine alto a basso ordine o basso ordine a alto ordine) è definito dall'implementazione. L'allineamento dell'unità di memoria indirizzabile non è specificato.

Quindi, l'ordine deve essere documentato dall'implementazione del compilatore.

Tuttavia, l'implementazione o la non specificazione dell'implementazione di bitfield implementano o non specificano che utilizzarli per modellare hardware, filo-protocollo o campi di bit di formato file in modo portatile non valga la pena di tentare.

Se si desidera che i 'campi di bit' di modellare qualcosa di esterno al vostro programma (come le cose di cui sopra), utilizzare le maschere esplicite, apparecchiare e sparecchiare i bit usando gli operatori standard bit-saggio (|, '& , ~ , < < `, ecc.). Usa le funzioni in linea di aiuto (o anche i macro se devi) per rendere questo più facile/chiaro nel tuo codice.

+2

+10 se potessi. La tua risposta a questa domanda è la migliore ragione per non usare bitfield per la cosa principale che la gente pensa che sia utile. –

+0

Non mi sono reso conto che la gente cerca di usarli come portabili, l'unico uso che ho visto è "parlare con l'hardware del mio programma che usa il compilatore X". E guarda tutte le migliaia di domande "Faccio questo in compilatore X, come faccio a farlo nel compilatore Y". –

+0

@CodeAbominator: ad esempio, ho visto campi bit usati per decifrare messaggi di protocollo di rete o formati di file binari. Ho anche visto alcuni di quel codice non funzionare quando compilato per una piattaforma diversa. –

2

Se si sta chiedendo quali bit in myBitField sono memorizzati in quali bit del byte in memoria, ciò è esplicitamente indefinito dagli standard C. Dovrai imparare dalla sperimentazione. Probabilmente vale la pena, se stai facendo qualcosa in cui questo è davvero importante, utilizzare invece un approccio in cui #finefile field1 come valore esadecimale (ad esempio, 0x40 o 0x02) e mettilo dove vuoi.

+0

Sfortunatamente, il test funzionale di questa porzione di codice è di almeno settimane, se non di mesi. (C'è molto che deve essere scritto per testarlo veramente perché sono a un punto in cui tutto ciò che rimane da scrivere è più o meno interdipendente su tutto il resto.) Le costanti definite sono un'opzione, ma preferirei utilizzare i campi di bit perché il primo richiederebbe un * lotto * più logica nel mio codice. –

+1

Bene, un rapido esperimento dovrebbe mostrarti cosa sta facendo il compilatore adesso ... basta definire l'unione come sopra, assegnare 0 a 'myVar4', quindi assegnare 1 a' field1' e stampare il valore risultante da 'myVar4'. Metterei un nome sul bit inutilizzato che hai definito prima di 'field1', tuttavia, per evitare che il compilatore lo ottimizzi. – jmaynard

4

Visual Studio 2008 docs compilatore indicano:

L'ordinamento dei dati dichiarati come campi di bit è da bassa ad alta po

Da "C++ Bit Fields", MSDN C++ Language Reference, Visual Studio 2008 version

+0

Come altri hanno notato, gli standard rilevanti non lo specificano, ed è bello scrivere codice conforme agli standard, ma questa è la risposta alla domanda che è stata posta, e il lettore può decidere se vogliono usare i loro poteri per il bene o per fantastico. ; P – rakslice

Problemi correlati