2011-02-05 18 views
13

posso fidarmi del fatto che il compilatore C esegue il modulo 2^n ogni volta che accedo a un campo di bit? O c'è qualche compilatore/ottimizzazione in cui un codice come quello qui sotto non stamperebbe Overflow?Overflow nei campi di bit

struct { 
    uint8_t foo:2; 
} G; 

G.foo = 3; 
G.foo++; 

if(G.foo == 0) { 
    printf("Overflow\n"); 
} 

Grazie in anticipo, Florian

+0

cosa intendi? L'hai chiesto esplicitamente di memorizzare i dati in due bit. Inoltre, 3 + 1 == 0 mod 4 –

+0

Sarei più preoccupato di cosa succede a quel bit se hai altri bitfield dichiarati in quella struttura. per esempio. uint8_t bar: 2; uint8_t pippo: 2; uint8_t cacca: 2; interesserebbe la barra o la cacca? – Dave

+0

Cosa significa foo: 2? – CharlesB

risposta

11

Sì, puoi fare affidamento sul compilatore C per fare la cosa giusta qui, purché il campo bit sia dichiarato con un tipo senza segno, che hai con uint8_t. Dallo standard C99 §6.2.6.1/3:

I valori memorizzati in campi di bit non firmati e oggetti di tipo unsigned char devono essere rappresentati utilizzando una pura notazione binaria. 40)

Da §6.7.2.1/9:

Un campo di bit viene interpretato come un tipo intero con o senza segno costituito dal numero di bit specificato. 104) Se il valore 0 o 1 è memorizzato in un campo di bit di larghezza diversa da zero di tipo _Bool, il valore del campo di bit deve essere uguale al valore memorizzato.

E da §6.2.5/9 (enfasi mia):

L'intervallo di valori negativi di tipo intero con segno è un sottoinsieme di tipo intero senza segno corrispondente, e la rappresentazione del lo stesso valore in ogni tipo è lo stesso. 31)Un calcolo che coinvolge operandi senza segno non può mai eccedere, perché un risultato che non può essere rappresentato dal tipo di intero senza segno risultante viene ridotto modulo il numero che è maggiore del valore più grande che può essere rappresentato dal tipo risultante.

Quindi sì, si può essere sicuri che qualsiasi compilatore standard conformi dovrà G.foo troppo pieno a 0 senza altri effetti collaterali indesiderati.

+0

Come indicato da R .. in un commento qui sotto, il calcolo è in realtà un calcolo firmato. Ciò non cambia la risposta qui, ma sarebbe, ad esempio, con un bitfield senza segno a 31 bit su un'architettura in cui gli interi sono a 32 bit (dove potrebbe esserci un overflow con segno non definito). –

3

No. Il compilatore alloca 2 bit al campo, e incrementando 3 risultati in 100b, che quando inseriti in due risultati bit in 0.

0

Risposta breve : sì, puoi fidarti che il modulo 2^n accada.

Nel tuo programma, G.foo++; equivale a G.foo = (unsigned int)G.foo + 1.

L'aritmetica int unsigned produce sempre risultati 2^(dimensione di unsint int in bit). I due bit di peso minimo vengono quindi memorizzati in G.foo, producendo zero.

+0

La tua equivalenza è sbagliata. 'uint8_t' sarà promosso a' int', non 'unsigned int'. 'G.foo ++;' è equivalente a 'G.foo = ((int) G.pippo + 1)% 4; '. –

+0

@R .. Hai ragione (ottengo sempre queste promozioni sbagliate), ma poi c'è qualcosa che manca nella risposta di Adam sopra, che è che il +1 sta effettivamente avvenendo tra le parti firmate. –

Problemi correlati