Sto provando a stampare char valore positivo:Come stampare un carattere senza segno in C?
char ch = 212;
printf("%u", ch);
ma ottengo:
4294967252
come posso ottenere 212
in uscita?
Sto provando a stampare char valore positivo:Come stampare un carattere senza segno in C?
char ch = 212;
printf("%u", ch);
ma ottengo:
4294967252
come posso ottenere 212
in uscita?
dichiarare il vostro ch
come
unsigned char ch = 212 ;
E il vostro printf funzionerà.
Questo perché in questo caso il tipo char
è firmato sul sistema *. Quando ciò accade, i dati vengono estesi dal segno durante le conversioni predefinite mentre si passano i dati alla funzione con un numero variabile di argomenti. Dal momento che 212 è maggiore di 0x80, è trattata come negativo, %u
interpreta il numero come un gran numero positivo:
212 = 0xD4
Quando è segno-esteso, FF
s sono pre-pended al vostro numero, in modo che diventi
0xFFFFFFD4 = 4294967252
che è il numero che viene stampato.
Si noti che questo comportamento è specifico per l'implementazione. In base alle specifiche C99, tutti i tipi char
vengono promossi a (firmato) int
, perché un int
può rappresentare tutti i valori di un char
, con o senza segno:
6.1.1.2: Se un
int
può rappresentare tutti i valori della tipo originale, il valore viene convertito inint
; in caso contrario, viene convertito inunsigned int
.
Ciò provoca passaggio di un int
un formato specificatore %u
, che prevede un unsigned int
.
Per evitare un comportamento indefinito nel programma, aggiungere il tipo esplicito getta come segue:
unsigned char ch = (unsigned char)212;
printf("%u", (unsigned int)ch);
char
fino alla realizzazione. Vedi
this question per maggiori dettagli.
Questa risposta è confusa e imprecisa.Le frasi sull'estensione del segno e sul trattamento 212 sono presentate senza contesto, senza riuscire a spiegare dove si applicano (la frase precedente si applica a un'operazione successiva, la promozione intera del 'char' quando viene usata come argomento, mentre la frase successiva si applica a una precedente operazione, inizializzazione del 'char' con un' int'). –
L'affermazione che 212 è considerata negativa perché è maggiore di 0x80 è falsa. Innanzitutto, l'inizializzazione di un 'char' firmato con 212 causa l'overflow dei numeri interi nella maggior parte delle implementazioni C, quindi il comportamento non è definito. In molte implementazioni C, ciò comporta il troncamento della rappresentazione del complemento a due da 212 a 8 bit, il che fa interpretare i bit come un valore negativo perché il bit 0x80 è impostato, non perché il valore iniziale è maggiore di 0x80 (i controesempi includono 0x80 e 0x100). –
Dopo l'inizializzazione di 'char', viene usato come argomento per' printf'. Le promozioni intere vengono eseguite, risultando in un 'int' negativo passato a' printf'. Ancora una volta, molte implementazioni C usano il complemento a due, quindi viene eseguita un'estensione del segno, come dice questa risposta. Convertire il valore in 'unsigned' a questo punto produrrebbe un grande numero positivo. Tuttavia, questa risposta non riesce a spiegare che il comportamento effettivo non è definito dallo standard C poiché viene passato un 'int' per un identificatore di'% u', che si aspetta un 'int unsigned '. –
L'intervallo di caratteri è compreso tra 127 e -128. Se assegni 212, ch memorizza -44 (212-128-128) non 212.Quindi se provi a stampare un numero negativo come non firmato ottieni (valore MAX di unsigned int) -abs (numero) che in questo caso è 4.294.967,252 mila
Quindi, se si desidera memorizzare 212 come è nel ch l'unica cosa che si può fare è dichiarare ch come
unsigned char ch;
ora la gamma di ch va da 0 a 255.
"L'intervallo di caratteri è compreso tra 127 e -128." - No, l'intervallo è definito dall'implementazione. –
@Jim Cosa intendi? – banarun
Intendo quello che ho detto ... era molto chiaro. Un char non è nemmeno necessariamente 8 bit, lasciati necessariamente firmati. –
Ci sono due errori in questo codice. Innanzitutto, nella maggior parte delle implementazioni C con firma char
, c'è un overflow in char ch = 212
perché 212 non si adatta a un 82 bit firmato char
e lo standard C non definisce il comportamento quando c'è un numero intero di overflow. Dovrebbe essere invece:
unsigned char ch = 212;
In secondo luogo, in printf("%u",ch)
, ch
sarà promosso a un int
nelle normali implementazioni C. Tuttavia, lo specificatore %u
prevede uno unsigned int
e lo standard C non definisce il comportamento quando viene passato il tipo errato. Dovrebbe essere invece:
printf("%u", (unsigned) ch);
Vorrei suggerire di usare static_cast invece del cast vecchio stile – ShitalShah
@ShitalShah: La domanda è codificata con C, non C++. C non ha un operatore static_cast. –
Ah .. non l'ho visto. – ShitalShah
Perché char
è di default signed
dichiarato che significa che la gamma della variabile è
-127 a +127>
il tuo valore è traboccato. Per ottenere il valore desiderato devi dichiarare il modificatore unsigned
. (unsigned
) la gamma del modificatore è:
0 to 255
per ottenere la gamma di qualsiasi tipo di dati seguire il processo 2^bit
esempio char
è 8 bit di lunghezza per ottenere la sua gamma solo 2 ^(power) 8
.
Nel caso in cui non si può modificare la dichiarazione per qualsiasi motivo, si può fare:
char ch = 212;
printf("%d", (unsigned char) ch);
Anche con 'ch' cambiato in' char' non firmato, il comportamento del codice non è definito dallo standard C. Questo perché il 'char unsigned 'è promosso a un' int' (nelle normali implementazioni C), quindi un 'int' viene passato a' printf' per lo specificatore '% u'. Tuttavia, '% u' si aspetta un' unsigned int', quindi i tipi non corrispondono, e lo standard C non definisce il comportamento. –
Il tuo commento non è corretto. Lo standard C11 afferma che lo specificatore di conversione deve essere dello stesso tipo della funzione 'argument' stessa, non del tipo promosso. Questo punto è anche affrontato in modo specifico nella descrizione del modificatore di lunghezza 'hh': " l'argomento sarà promosso in base alle promozioni intere, ma il suo valore sarà convertito in char con segno o senza segno prima di stampare " –
Solo lavorato dopo il cast esplicito a 'unsigned int' quando viene passato a' prtinf() '. L'aggiunta di -std = c11 al comando gcc-4.8.4 per applicare lo standard non ha avuto alcun effetto. – ypx