2012-08-07 4 views
7

il programma è:tipo di bit di stampa come intero? Come è la conversione?

typedef struct xp { 
     int a:2; 
     int b:2; 
     int c:1; 
} xp; 

int main(void) 
{ 
     xp x; 
     memset(&x, 0, sizeof(xp)); 

     x.a = 1; 
     x.b = 3; 
     x.c = 1; 

     printf("%d\n",x.a); 
     printf("%d\n",x.b); 
     printf("%d\n",x.c); 

     return 0; 
} 

ottengo 1 -1 -1, perché? Come sono memorizzati a, bec in x? Cosa è successo quando printf ("% d \ n", x.a); viene eseguito?

+0

Si tratta di un duplicato; So che una volta ho risposto esattamente a questa domanda. Vedrò se riesco a rintracciarlo. –

+0

Fino Carl trova la vittima: perché il compilatore interpreta i bit-field come numeri in complemento a due. –

+2

In realtà è definito dall'implementazione indipendentemente dal fatto che siano firmati o non firmati. –

risposta

5

Stai utilizzando un tipo firmato per i vostri campi di bit, il che significa che hai creato ciò che equivale a due interi con segno a due bit, e un intero firmato un bit.

I valori possibili per un intero con segno a due bit (complemento a due) sono: -2, -1, 0, e 1:

I valori possibili per un intero segnato un bit (complemento a due) sono -1 e 0.

Memorizzando i valori che "non si adattano", come avete fatto in queste righe:

x.b = 3; 
x.c = 1; 

otterrete comportamenti strani come i modelli di bit memorizzati vengono interpretati in modo diverso quando leggere. Si può avere una simile esperienza facendo qualcosa di simile:

char x = 58147; 

su una macchina con un char tipo a 8 bit, che il valore non si adatta, così potrai leggere qualcosa di diverso indietro quando si accede x.

+0

@ccsnailpp, è -1, perché è in complemento a due. Il primo bit è un 1, quindi significa che è un numero negativo. Per tradurre il numero positivo corrispondente, fai '~ x + 1'. In questo caso è '~ 11 + 1 = 00 + 1 = 1'.Nel complemento a due, un modello di bit di tutti gli uni rappresenta sempre -1. –

+0

grazie per la tua spiegazione in dettaglio. –

2

Un campo di bit di tipo int è sia di tipo signed int o di tipo unsigned int. La scelta è definita dall'implementazione. Questo è per ragioni storiche. Questo è l'unico contesto in cui int e signed int possono differire.

Questo è riportato alla sezione 6.7.2 della norma C (C99 draft, C11 draft), seguendo un elenco di specificatori di tipo:

Ciascuna delle multinsiemi separate da virgole designa stesso tipo, tranne che per i campi bit, è definito dall'implementazione se lo specificatore identifica loo lo stesso tipo come unsigned int.

La soluzione è evitare l'uso di int per i campi bit; dichiararli sempre come signed int o come unsigned int. (Quest'ultimo fa quasi sempre più senso.)

Problemi correlati