2012-08-07 13 views
7

del programa es:¿tipo de bit de impresión como número entero? ¿Cómo es la conversión?

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; 
} 

me sale 1 -1 -1, ¿por qué? ¿Cómo se almacenan a, byc en x? ¿Qué pasó cuando printf ("% d \ n", x.a); ¿es ejecutado?

+0

Esto es un duplicado; Sé que respondí exactamente esta pregunta una vez. Veré si puedo rastrearlo. –

+0

Hasta que Carl encuentre el engañado: porque su compilador interpreta los campos de bits como números complementarios de dos. –

+2

En realidad, está definido por la implementación ya sea que estén firmados o no. –

Respuesta

5

Está utilizando un tipo con signo para sus campos de bits, lo que significa que ha creado lo que equivale a dos enteros con signo de dos bits y un entero con signo de un bit.

Los valores posibles para un entero con signo de dos bits (complemento a dos) son: -2, -1, 0, y 1:

Los valores posibles para un entero con signo de un bit (de complemento de dos) son -1 y 0.

al almacenar los valores que "no encajan", al igual que ha hecho en estas líneas:

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

va a conseguir un comportamiento extraño ya que los patrones de bits que almacena son interpretados de manera diferente cuando leer. Puede tener una experiencia similar haciendo algo como:

char x = 58147; 

en una máquina con un tipo 8 bit char, ese valor no se ajusta, por lo que va a leer algo diferente cuando se accede a volver x.

+0

@ccsnailpp, es -1 porque es complemento de dos. El bit inicial es un 1, por lo que significa que es un número negativo. Para traducir al número positivo correspondiente, haz '~ x + 1'. En este caso, eso es '~ 11 + 1 = 00 + 1 = 1'.En el complemento a dos, un patrón de bits de uno a uno siempre representa -1. –

+0

gracias por su explicación en detalle. –

2

Un campo de bit del tipo int es del tipo signed int o del tipo unsigned int. La elección es definida por la implementación. Esto es por razones históricas. Este es el único contexto en el que int y signed int pueden diferir.

Esto se especifica en la sección 6.7.2 de la norma C (C99 draft, C11 draft), siguiendo una lista de especificadores de tipo:

Cada uno de los conjuntos múltiples separados por comas designa del mismo tipo, excepto que para los campos de bits, está definido por la implementación si el especificador int designa el mismo tipo que signed int o el mismo tipo como unsigned int.

La solución es evitar el uso simple int para campos de bits; siempre declararlos como signed int o como unsigned int. (Esto último casi siempre tiene más sentido.)

Cuestiones relacionadas