2012-03-04 34 views
6

En el siguiente código:promoción tipo de datos en C

#include "stdio.h" 
signed char a= 0x80; 
unsigned char b= 0x01; 


void main (void) 
{ 
    if(b*a>1) 
     printf("promoted\n"); 
    else if (b*a<1) 
     printf("why doesnt promotion work?"); 

    while(1); 
} 

que esperaba "ascendieron' a ser impreso pero, duerma Por qué Si puedo los tipos de datos a int firmado y sin firmar, y tener un tan..? un número negativo, por ejemplo, 0x80000000 y B como un número positivo, 0x01, "promovido" se imprime como se esperaba.

PLZ me ayudan a entender cuál es el problema!

Respuesta

10

acabas de ser atrapado por el desordenado reglas de promoción de tipos de C.

En C, los intermedios del tipo integral más pequeños que int se promueven automáticamente a int.

Así que tienes:

0x80 * 0x01 = -128 * 1 

0x80 consigue con signo extendido para escribir int:

0xffffff80 * 0x00000001 = -128 * 1 = -128 

Así, el resultado es -128 y por lo tanto es menos de 1.


Cuando se utiliza el tipo int y unsigned int, ambos operandos son ascendidos a unsigned int. 0x80000000 * 0x01 = 0x80000000 como un entero sin signo es mayor que 1.


Así que aquí está la comparación lado a lado de la promoción tipo que está teniendo lugar:

(signed char) * (unsigned char) -> int 
(signed int) * (unsigned int) -> unsigned int 

(signed char)0x80  * (unsigned char)0x01 -> (int)   0xffffff80 
(signed int)0x80000000 * (unsigned int)0x01 -> (unsigned int)0x80000000 

(int)   0xffffff80 is negative -> prints "why doesnt promotion work?" 
(unsigned int)0x80000000 is positive -> prints "promoted" 

Here's a reference to the type-promotion rules of C.

+0

@Mystical No entiendo tu respuesta. Incluso si se firma extendido para escribir int, lo que no creo que ocurra, pero suponiendo que lo haga, ¿por qué no se promueve a unsigned int y el producto es un número + ve? – Dom045

+0

+1 - Esta respuesta es mucho mejor/más relevante que la mía por una milla larga (así que la eliminé) –

+0

@ Dom045 Porque la especificación lo dice. Tanto 'signed char' como' unsigned char' son tipos inferiores a 'int'. Entonces ambos serán promovidos a 'int'. En el caso 'signed int' vs.' unsigned int', el estándar dicta que ambos se convertirán en 'unsigned int'. Las reglas se pueden encontrar aquí: https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+Understand+integer+conversion+rules – Mysticial

2

La razón printf("promoted\n"); nunca se es porque b*a es siempre == -128 , que es menos que 1

a  b  
0x80 * 0x01 = -128 * 1 
Cuestiones relacionadas