2016-07-12 35 views
6

Ho questa definizione:Come cancellare tutti i campi in una struttura bit field, tranne uno?

typedef struct { 
    int foo :1; 
    int bar :1; 
    int baz :1; 
    ... 
} bitfield; 
bitfield bf = {0}; 

Nel mio codice voglio cancellare l'intero campo di bit senza modificare bar.

Una soluzione potrebbe essere:

bool temp = bf.bar; 
*(*long)&bf = 0; 
bf.bar = temp; 

Esiste un modo corretto che non richiede alcun booleano temporanea?

+5

State attenti con quella radura, se si dispone di meno o uguale numero di bit che si inserisce in un 'int' poi su 64- macchine bit che potresti scrivere fuori dai limiti se 'sizeof (long) == 8' (cioè se' long' è 64 bit e 'int' è 32 bit). Stai anche infrangendo la rigida regola dell'aliasing con quel cast. Una soluzione migliore sarebbe usare 'memset' invece (come' memset (& bf, 0, sizeof bf) ') –

+3

Ehm, O vuoi cancellare tutto il bitfield o non lo fai! E il tuo codice richiama un comportamento indefinito. Un consiglio generale: non usare 'struct's bitfield. Usa mascheramento e sposta direttamente (sono comunque utilizzati dietro le quinte). – Olaf

+0

'* (* long) & bf = 0;' è un errore di sintassi –

risposta

10

C bitfield- struct s non sono un buon uso per bit singoli. Meglio usare uno unsigned int e spostare/mascherare. Questo viene fatto in background comunque. I migliori tipi di larghezza fissa, ad es. uint32_t, ecc.

Il codice nell'esempio richiama il comportamento non definito come già indicato in un commento. Si viola la regola del tipo efficace (alias rigoroso). Non usarlo mai così.

Tuttavia, è possibile utilizzare un composto letterale:

bf = (bitfield){ .bar = bf.bar }; 

per mantenere .bar e impostare tutti gli altri campi per 0.

Nota: esiste un altro problema con il codice: si utilizza int. È specifico dell'implementazione se un bitfield con tipo int è effettivamente firmato o non firmato. Quindi ogni campo può contenere 0 e 1 o 0 e -1 in implementazioni tipiche. Quindi lasci questo alla realizzazione. _Bool OTOH è sempre senza segno con i valori 0 e 1. Questo è lo stesso degli operatori logici. dei campi migliori booleani direttamente:

typedef struct { 
    bool foo : 1; 
    ... 
} bitfield; 

(Mind the le ; s)

+0

Potresti elaborare il tuo primo argomento. Sto usando campi di bit su un target embedded che migliorano notevolmente la leggibilità e la modularità. Posso concordare che il mascheramento e lo spostamento sono la soluzione più ottimizzata per la manipolazione dei bit, ma sono anche soggetti a errori. – nowox

+0

Il letterale composto è quello che stavo cercando ... – nowox

+0

@nowox: Non aumentano effettivamente la modularità. E la leggibilità è una questione di preferenza. Usa un 'enum' per nominare i bit e usa' uint32_t i = '1 << BF_BAR;' per esempio per avere solo un bit impostato. Utilizzando un insieme di macro comuni per set/clear/test un po 'lo renderà chiaro. Non uso 'struct's bitfield ** specialmente sui sistemi embedded. Si noti che lo standard non garantisce quasi nulla su come sono strutturate le strutture bitfield, ecc. Per me, sono un no-go. E ottenere l'abitudine di utilizzare tipi di larghezza fissa e fare attenzione a usare interi con segno! – Olaf