Char è firmato o non firmato per impostazione predefinita?


158

Nel libro "Riferimento completo di C" è menzionato che charper impostazione predefinita è senza segno.

Ma sto provando a verificarlo con GCC e Visual Studio. Lo sta prendendo come firmato di default.

Quale è corretto?


5
L'unico libro di consultazione C di cui mi fido è "C: A Reference Manual" di Harbison & Steele ( careferencemanual.com ). Ovviamente lo standard è l'ultima parola, ma non è molto leggibile e fornisce solo la minima informazione sugli usi pre-standard e comuni (es. POSIX) che sono al di fuori dello standard. Harbison & Steele è abbastanza leggibile, dettagliato e probabilmente più corretto della maggior parte dei riferimenti. Tuttavia, non è nemmeno un tutorial, quindi se ti trovi nelle fasi iniziali dell'apprendimento, probabilmente non è una buona cosa saltare dentro.
Michael Burr,

15
Penso che il libro che stai leggendo sia C: The Complete Reference , di Herbert Schildt. Da una recensione di questo libro ( accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm ): non ho intenzione di raccomandare questo libro (troppi di voi danno troppo peso alle mie opinioni) ma Non credo che meriti lo stesso opprobrio che è stato legittimamente gettato in alcuni dei suoi altri lavori. Come dice Michael, un riferimento molto migliore è Harbison & Steele .
Alok Singhal,

I miei due centesimi qui: Perché charpuò essere senza segno, come regola empirica usare un intper leggere un valore usando getchar(), che potrebbe restituire EOF. EOFviene generalmente definito come -1o altro valore negativo, che la memorizzazione in un unsignednon è ciò che si desidera. Ecco la dichiarazione: A extern int getchar();proposito, questa raccomandazione proviene anche dal libro "C: A Reference Manual".
Maxim Chetrusca,

6
L'unico riferimento C di cui mi fido è ISO / IEC 9899: 2011 :-)
Jeff

3
@MaxChetrusca un buon consiglio ma una cattiva logica: anche sul charcaso firmato , dovresti usare intper memorizzare il valore di ritorno.
Antti Haapala,

Risposte:


204

Il libro è sbagliato Lo standard non specifica se plain charè firmato o non firmato.

In effetti, lo standard definisce tre tipi distinti: char , signed chare unsigned char. Se #include <limits.h>poi guardi CHAR_MIN, puoi scoprire se plain charè signedo unsigned(se CHAR_MINè inferiore a 0 o uguale a 0), ma anche in questo caso, i tre tipi sono distinti per quanto riguarda lo standard.

Si noti che charè speciale in questo modo. Se si dichiara una variabile in intquanto è equivalente al 100% a dichiararla come signed int. Questo è sempre vero per tutti i compilatori e le architetture.


1
@Alok: lo stesso non è vero per alcuni altri tipi di dati, ad esempio intsignifica signed intsempre, giusto? A parte char, in quali altri tipi di dati hanno la stessa confusione C?
Lazer,

8
@eSKay: sì, charè l'unico tipo che può essere firmato o non firmato. intè equivalente ad signed intesempio.
Alok Singhal,

28
C'è una ragione isterica, ehm, storica per questo - all'inizio della vita di C lo "standard" è stato capovolto almeno due volte, e alcuni compilatori primi popolari sono finiti in un modo e altri nell'altro.
Hot Licks,

9
@AlokSinghal: è anche definito dall'implementazione se un campo di tipo bit intè firmato o non firmato.
Keith Thompson,

@KeithThompson grazie per la correzione. Tendo a dimenticare alcuni dettagli sui tipi di campi bit poiché non li uso molto.
Alok Singhal

67

Come sottolinea Alok , lo standard lascia questo fino all'implementazione.

Per gcc, il default è firmato, ma puoi modificarlo con -funsigned-char. nota: per gcc in Android NDK, il valore predefinito è unsigned . Puoi anche chiedere esplicitamente caratteri firmati con -fsigned-char.

Su MSVC, l'impostazione predefinita è firmata ma è possibile modificarla con /J.


2
È interessante notare che la descrizione di Schildt non corrisponde al comportamento di MSVC poiché i suoi libri sono generalmente orientati verso gli utenti di MSVC. Mi chiedo se MS ha cambiato il default a un certo punto?
Michael Burr,

1
Ho pensato che non dipendesse dal compilatore, ma dalla piattaforma. Pensavo che char fosse lasciato come terzo tipo di "tipo di dati carattere" per conformarsi a ciò che i sistemi in quel momento usavano come caratteri stampabili.
Spidey,

10
I documenti di GCC dicono che dipende dalla macchina: " Ogni tipo di macchina ha un valore predefinito per quale carattere dovrebbe essere. È come un carattere senza segno per impostazione predefinita o come un carattere firmato per impostazione predefinita. "
Deduplicator

1
Potete per favore fornire una fonte per la vostra nota che su Android il valore predefinito è unsigned char?
phlipsy il

1
@Spidey lo standard C non fa alcuna distinzione reale tra compilatori, piattaforme e architetture CPU. Li raggruppa tutti insieme in "implementazione".
lavaggio:

35

C99 N1256 bozza 6.2.5 / 15 "Tipi" ha questo da dire sulla firma del tipo char:

L'implementazione deve definire il carattere in modo che abbia lo stesso intervallo, rappresentazione e comportamento del carattere con segno o del carattere senza segno.

e in una nota a piè di pagina:

CHAR_MIN, definito in <limits.h>, avrà uno dei valori 0o SCHAR_MINe questo può essere usato per distinguere le due opzioni. Indipendentemente dalla scelta effettuata, charè un tipo separato dagli altri due e non è compatibile con nessuno dei due.


7

Secondo il libro The C Programming Language di Dennis Ritchie, che è di fatto il libro standard per ANSI C, i caratteri semplici firmati o non firmati dipendono dalla macchina, ma i caratteri stampabili sono sempre positivi.


9
Non è necessariamente il caso che i caratteri stampabili siano sempre positivi. Lo standard C garantisce che tutti i membri del set di caratteri di esecuzione di base abbiano valori non negativi.
Keith Thompson,

7

Secondo lo standard C, la firma del carattere normale è "definita dall'implementazione".

In generale, gli implementatori hanno scelto quale fosse più efficiente da implementare sulla loro architettura. Sui sistemi x86 il char è generalmente firmato. Sui sistemi arm è generalmente senza segno (Apple iOS è un'eccezione).



2
@plugwash La tua risposta è stata probabilmente sottoposta a votazione negativa perché Tim Post ha perso le sue chiavi . Scherzi a parte, non dovresti preoccuparti di un singolo downvote fintanto che sei sicuro che la tua risposta sia corretta (che è in questo caso). Mi è capitato più volte di fare il downgrade dei miei post senza motivo valido. Non preoccuparti, a volte le persone fanno solo cose strane.
Paperino

1
Perché il char firmato è più efficiente su x86? Qualche fonte?
martinkunev,

2

Secondo "Il linguaggio di programmazione C ++" di Bjarne Stroustrup, char"l'implementazione è definita". Può essere signed charo in unsigned charbase all'implementazione. Puoi verificare se charè firmato o meno utilizzando std::numeric_limits<char>::is_signed.


9
Questa è una domanda C. C ++ è un linguaggio diverso e i riferimenti C ++ non hanno rilevanza per C.
MM

1

Ora, sappiamo che lo standard lascia l'implementazione.

Ma come controllare un tipo è signedo unsigned, come char?

Ho scritto una macro per fare questo:

#define IS_UNSIGNED(t) ((t)~1 > 0)

e testarlo con gcc, clange cl. Ma non sono sicuro che sia sempre sicuro per altri casi.


Cosa c'è di sbagliato nel solito CHAR_MIN <0 (o WCHAR_MIN <0 per wchar_t)?
Öö Tiib,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.