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?
risposta
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
.
Ti capita di avere il riferimento standard a quelle regole? –
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. –
Ho capito, molte grazie –
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
.
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. –
penso che sia a causa di integer promotion
Un buon post sul blog su questo concetto: http://www.idryman.org/blog/2012/11/21/integer-promotion/
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.
google "promozione intera" –
Leggi la mia risposta in basso –
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. –