output di char non firmato di un char firmato

Ho il codice seguente:

char x = -1; int y = x; printf("%u\n", x); printf("%u\n", y); 

L’output è:

 4294967295 4294967295 

Non capisco perché x può avere un tale valore. So che il valore massimo di un char unsigned è 255 e per un char firmato 127. Come può essere 4294967295?

Per funzioni come printf che usano argomenti variadici, qualsiasi tipo di integrale più piccolo di un int ( char e short ) viene implicitamente promosso a int . Lo stesso è vero con i numeri in virgola mobile, float è promosso a double .

Quindi, il tuo char viene esteso al segno con un valore int con valore -1 , e dal momento che lo stai stampando come non firmato, nel complemento a 2 ottieni UINT_MAX .

Modifica: come segue, se il tuo char impostato su unsigned (questo dipende dal tuo compilatore / piattaforma), la risposta sarà invece 255 . Quando si verifica la promozione, il valore sarà esteso a zero anziché esteso al segno.

La variabile ha il valore -1. ma hai specificato% u (unsigned int) nel printf

int è a 32 bit quindi 2 ^ 32 = 4294967296 => -1 + 4294967296 = 4294967295 spero che tu lo capisca.

Stai utilizzando male un identificatore di formato e invocando un comportamento indefinito a causa di ciò. La mia comprensione è che, in ogni caso, il numero di convertiti alla rappresentazione binaria del complimento è uguale per -1 o 4294967295. Ecco perché% u per le stampe firmate 4294967295 ignorando -ve bit più a sinistra. Quando viene utilizzato% d per l’int firmato, utilizza il bit più a sinistra come flag -ve e stampa -1. Allo stesso modo% u per il valore senza segno delle stampe non firmate ma% d induce a trattare il numero come firmato e quindi stampa -1

Se il qualificatore di input è signed , fai attenzione al bit del segno, se il bit del segno è 1, otterrai un valore negativo. Sebbene x sia signed char , si sta aspettando 1 byte valore di 1 byte , ma si ottiene un valore di 4 byte causa del meccanismo di copia bit di segno .

x valore:

 x = -1 = 0000 0000 0000 0000 0000 0000 1111 1111 | sign bit, this bit get's copied into remaining bytes, so it becomes like = 1111 1111 1111 1111 1111 11111 1111 1111 => calculates this => 4294967295 = | sign bit , now you are printing in %u format ie unsigned so it will ignore signed bit and you are getting big value. 

Lo stesso se si stampa in formato %d o %i

 printf("%d\n", x); // it prints -1 bcz %d will check sign bit which is 1 ie it will prints -ve value, so it's prints -1 

Ho solo cercato di spiegare il motivo per cui si sta ottenendo tale output, ma è un undefined behaviour come menzionato in alcuni commenti se non si utilizza l’identificatore di formato corretto. puoi riferirti a diversi standard C.

EDIT: per giustificare il mio punto (macchina Linux) consideriamo sotto il codice

 int main() { unsigned char x = -1; printf("%u\n",x); /*In above printf input is unsigned, so compiler won't check sign bit, even though sign bit is 1, result will be +ve only. */ printf("%d\n",x);//some of you may expects -1 because of %d, it's wrong. /* In above printf it's printing 255 not because of format specifier, it's because of your input qualifier(which is unsigned in this case) */ return 0; }