¿Char está firmado o no está firmado por defecto?

158

En el libro "Referencia completa de C" se menciona que charpor defecto no está firmado.

Pero estoy tratando de verificar esto con GCC y Visual Studio. Lo está tomando como firmado por defecto.

¿Cuál es el correcto?

C alumno
fuente
55
El único libro de referencia C en el que confío es "C: A Reference Manual" de Harbison & Steele ( careferencemanual.com ). Por supuesto, el estándar es la última palabra, pero no es muy legible y solo brinda la más mínima información sobre usos pre-estándar y comunes (es decir, POSIX) que están fuera del estándar. Harbison & Steele es bastante legible, detallado y probablemente más correcto que la mayoría de las referencias. Sin embargo, tampoco es un tutorial, por lo que si estás en las etapas iniciales de aprendizaje, probablemente no sea una gran cosa para saltar.
Michael Burr el
15
Creo que el libro que estás leyendo es C: The Complete Reference , de Herbert Schildt. De una revisión de este libro ( accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm ): No voy a recomendar este libro (muchos de ustedes dan demasiado peso a mis opiniones) pero No creo que merezca el mismo oprobio que se ha arrojado legítimamente a algunos de sus otros trabajos. Como dice Michael, una referencia mucho mejor es Harbison & Steele .
Alok Singhal el
Mis dos centavos aquí: porque charpuede ser sin signo, como regla general, use un intpara leer un valor usando getchar(), lo que podría devolver EOF. EOFgeneralmente se define como -1u otro valor negativo, que almacenar en un unsignedno es lo que desea. Aquí está la declaración: extern int getchar();Por cierto, esta recomendación también proviene del libro "C: A Reference Manual".
Maxim Chetrusca
66
La única referencia C en la que confío es ISO / IEC 9899: 2011 :-)
Jeff
3
@MaxChetrusca buenos consejos pero mala lógica: incluso en el charcaso firmado , tendría que usar intpara almacenar el valor de retorno.
Antti Haapala

Respuestas:

204

El libro esta equivocado. El estándar no especifica si plain charestá firmado o no.

De hecho, la norma define tres tipos distintos: char, signed char, y unsigned char. Si usted #include <limits.h>y luego mira CHAR_MIN, puede averiguar si chares simple signedo unsigned(si CHAR_MINes menor que 0 o igual a 0), pero aun así, los tres tipos son distintos en lo que respecta al estándar.

Tenga en cuenta que chares especial de esta manera. Si declara una variable ya intque es 100% equivalente a declararla como signed int. Esto siempre es cierto para todos los compiladores y arquitecturas.

Alok Singhal
fuente
1
@Alok: lo mismo no es cierto para algunos otros tipos de datos, por ejemplo, intsignifica signed intsiempre, ¿verdad? Además de char, ¿en qué otros tipos de datos tienen la misma confusión C?
Lazer
8
@eSKay: sí, chares el único tipo que se puede firmar o no. intes equivalente a signed intpor ejemplo.
Alok Singhal
28
Hay una razón histérica, er, histórica para esto: al principio de la vida de C, el "estándar" se volcó al menos dos veces, y algunos compiladores tempranos populares terminaron de una manera y otros de otra.
Hot Licks
9
@AlokSinghal: También está definido por la implementación si un campo de tipo de bit intestá firmado o no.
Keith Thompson
@KeithThompson gracias por la corrección. Tiendo a olvidar algunos detalles sobre los tipos de campo de bits ya que no los uso mucho.
Alok Singhal
67

Como señala Alok , el estándar lo deja a la implementación.

Para gcc, el valor predeterminado está firmado, pero puede modificarlo con -funsigned-char. nota: para gcc en Android NDK, el valor predeterminado es sin signo . También puede solicitar explícitamente caracteres firmados con -fsigned-char.

En MSVC, el valor predeterminado está firmado pero puede modificarlo con /J.

R Samuel Klatchko
fuente
2
Es interesante que la descripción de Schildt no coincida con el comportamiento de MSVC ya que sus libros generalmente están dirigidos a usuarios de MSVC. Me pregunto si MS cambió el valor predeterminado en algún momento?
Michael Burr el
1
Pensé que no dependía del compilador, sino de la plataforma. Pensé que char se dejó como un tercer tipo de "tipo de datos de caracteres" para ajustarse a lo que los sistemas en ese momento usaban como caracteres imprimibles.
Spidey
10
Los documentos de GCC dicen que depende de la máquina: " Cada tipo de máquina tiene un valor predeterminado para lo que debería ser. Es como un carácter sin signo por defecto o como un carácter firmado por defecto " .
Deduplicador
1
¿Puede proporcionar una fuente para su nota de que en Android el valor predeterminado es char sin firmar?
phlipsy
1
@Spidey, el estándar C no hace una distinción real entre compiladores, plataformas y arquitecturas de CPU. Simplemente los agrupa a todos bajo "implementación".
lavado el
35

C99 N1256 draft 6.2.5 / 15 "Tipos" tiene esto que decir sobre la firma del tipo char:

La implementación definirá char para que tenga el mismo rango, representación y comportamiento que el char con signo o el sin signo.

y en una nota al pie:

CHAR_MIN, definido en <limits.h>, tendrá uno de los valores 0o SCHAR_MIN, y esto puede usarse para distinguir las dos opciones. Independientemente de la elección realizada, chares un tipo separado de los otros dos y no es compatible con ninguno.

Michael Burr
fuente
7

De acuerdo con el libro The C Programming Language de Dennis Ritchie, que es el libro estándar de facto para ANSI C, los caracteres simples con o sin signo dependen de la máquina, pero los caracteres imprimibles siempre son positivos.

Ravi Rathi
fuente
9
No es necesariamente el caso de que los caracteres imprimibles sean siempre positivos. El estándar C garantiza que todos los miembros del juego de caracteres de ejecución básica tengan valores no negativos.
Keith Thompson
7

De acuerdo con el estándar C, la firma de char simple es "implementación definida".

En general, los implementadores eligieron el que fuera más eficiente para implementar en su arquitectura. En los sistemas x86, char generalmente está firmado. En los sistemas de brazo generalmente no está firmado (Apple iOS es una excepción).

lavado
fuente
2
@plugwash Su respuesta probablemente fue rechazada porque Tim Post perdió sus llaves . Sin embargo, en serio, no debe preocuparse por un solo voto negativo siempre y cuando esté seguro de que su respuesta es correcta (que es en este caso). Me han sucedido varias veces que mis publicaciones fueron rechazadas sin ningún motivo válido. No te preocupes por eso, a veces las personas simplemente hacen cosas extrañas.
Pato Donald
1
¿Por qué es firmado char más eficiente en x86? Alguna fuente?
martinkunev
2

De acuerdo con "El lenguaje de programación C ++" de Bjarne Stroustrup, chares "implementación definida". Puede ser signed charo unsigned chardepende de la implementación. Puede verificar si charestá firmado o no mediante el uso std::numeric_limits<char>::is_signed.

BoQ
fuente
9
Esta es una pregunta C. C ++ es un lenguaje diferente, y las referencias de C ++ no tienen relevancia para C.
MM
1

Ahora, sabemos que el estándar deja eso a la implementación.

Pero, ¿cómo verificar un tipo es signedo unsigned, como char?

Escribí una macro para hacer esto:

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

y probarlo con gcc, clangy cl. Pero no estoy seguro de que siempre sea seguro para otros casos.

南山 竹
fuente
¿Qué hay de malo con CHAR_MIN <0 (o WCHAR_MIN <0 para wchar_t)?
Öö Tiib