2013-07-24 10 views
5

Se la dimensione di byte è solo un byte, perché printf() si comporta come se fosse quattro byte?Perché printf applica un char a 8 bit a 32 bit?

+0

google "promozione intera" –

+0

Leggi la mia risposta in basso –

+0

Ho appena ricevuto un collegamento [Deep C: Integer Promotion] (http://www.idryman.org/blog/2012/11/21/integer-promotion/) spiega quello che stavo dicendo La sua implementazione dipende. –

risposta

14

Formalmente, il programma presenta un comportamento indefinito: %x specifica di formato si aspetta un argomento di tipo unsigned int, ma si sta passando un int, come spiegato di seguito (hat tip @R). In pratica ciò è innocuo con le moderne macchine a complemento a due, poiché int e unsigned hanno layout di bit compatibili. Ma ancora, tecnicamente, questo è un comportamento indefinito e sarebbe una buona idea ripararlo, come in printf("%x\n", (unsigned)byte);.

Le regole per il passaggio di parametri alle funzioni variadic affermano che tutti i tipi integrali di dimensioni inferiori a int vengono promossi a int. Altrimenti, come lo sarebbe printf, vedendo %x, se estrarre uno o quattro byte dallo stack? Dallo standard:

5.2.2p7:
Quando non esiste un parametro per un dato argomento, l'argomento viene passato in modo tale che la funzione di ricezione può ottenere il valore dell'argomento invocando va_arg (18.10)... Se l'argomento ha tipo integrale o di enumerazione che è soggetta alle promozioni integrali (4.5), o un tipo virgola mobile che è soggetta al punto promozione galleggiante (4.6), il valore dell'argomento viene convertito nel tipo promosso prima della chiamata.

Questo è il modo in cui il char si trasforma in un int. Non è specificato se char è firmato o non firmato, ma a quanto pare, sulla piattaforma che si utilizza è un tipo firmato. In questo modo viene esteso il segno quando viene promosso a int. 0xff è (char)-1, e 0xffffffff è (int)-1.

+0

Ti capita di avere il riferimento standard a quelle regole? –

+2

5.2.2p7 Quando non ci sono parametri per un dato argomento, l'argomento viene passato in modo tale che la funzione ricevente possa ottenere il valore dell'argomento invocando va_arg (18.10) ... Se l'argomento ha tipo integrale o di enumerazione che è soggetto alle promozioni integrali (4.5), o un tipo a virgola mobile che è soggetto alla promozione in virgola mobile (4.6), il valore dell'argomento viene convertito nel tipo promosso prima della chiamata. –

+0

Ho capito, molte grazie –

1

Un char è firmato a 8 bit. Il formato "%x\n" dice di stampare un numero intero. Quindi il valore di byte è esteso a un numero intero. Poiché un char di 0xff è, in tale contesto, un valore a 8 bit di -1, printf sta stampando solo il valore intero esadecimale di un -1, che è ffffffff.

+2

Su questa piattaforma, plain 'char' è una quantità a 8 bit con segno. Lo standard C dice esplicitamente che il semplice 'char' è firmato o non firmato è un dettaglio definito dall'implementazione. –

2

Hai invocato un comportamento indefinito passando il tipo di argomento sbagliato printf. Il %x specificatore richiede un argomento di tipo unsigned int, ma è passato (a causa di promozioni di default) un firmato int. Questo è validamente valido se il valore dell'argomento int firmato è non negativo, ma sul proprio sistema, è normale che char sia un tipo firmato, quindi byte contiene il risultato dell'applicazione di una conversione definita dall'implementazione su 0xff; il solito risultato di questa conversione è -1.

Problemi correlati