2012-03-04 24 views
6

Nel codice seguente:promozione tipo di dati in 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); 
} 

mi aspettavo "promosso' da stampare ma doesnt Perché Se posso i tipi di dati a int firmato e non firmato, e hanno un come..? un numero negativo, ad esempio, 0x80000000 e b come un numero positivo, 0x01, "promosso" viene stampato come previsto.

PLZ aiutarmi a capire qual è il problema!

risposta

10

hai appena stato catturato dal disordinato regole di promozione del tipo di C.

In C, i prodotti intermedi di tipo integrale inferiori a int vengono promossi automaticamente a int.

in modo da avere:

0x80 * 0x01 = -128 * 1 

0x80 ottiene firmata estesa a digitare int:

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

Così il risultato è -128 ed è inferiore a 1 così.


Quando si utilizza il tipo int e unsigned int, entrambi gli operandi ottenere una promozione a unsigned int. 0x80000000 * 0x01 = 0x80000000 come numero intero senza segno è maggiore di 1.


Quindi, ecco il confronto side-by-side della promozione tipo che sta avvenendo:

(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 Non capisco la tua risposta. Anche se viene firmato esteso per digitare int, quale non penso che faccia, ma supponendo che lo faccia, perché non viene promosso a unsigned int, e il prodotto è un numero + ve? – Dom045

+0

+1 - Questa risposta è molto migliore/più rilevante della mia per un lungo miglio (quindi l'ho cancellata) –

+0

@ Dom045 Perché la specifica lo dice. Sia 'signed char' che' unsigned char' sono tipi inferiori a 'int'. Quindi saranno entrambi promossi a 'int'. Nel caso 'signed int' vs.' unsigned int', lo standard impone che entrambi vengano convertiti in 'unsigned int'. Le regole possono essere trovate qui: https://www.securecoding.cert.org/confluence/display/seccode/INT02-C.+Understand+integer+conversion+rules – Mysticial

2

La ragione printf("promoted\n"); mai corre è perché b*a è sempre == -128 , che è inferiore a 1

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