Char é assinado ou não assinado por padrão?

158

No livro "Referência completa de C", é mencionado que, charpor padrão, não está assinado.

Mas estou tentando verificar isso com o GCC e com o Visual Studio. Está tomando como assinado por padrão.

Qual deles está correto?

C Learner
fonte
5
O único livro de referência C em que confio é o "C: A Reference Manual" da Harbison & Steele ( careferencemanual.com ). Obviamente, o padrão é a palavra final, mas não é muito legível e apenas fornece as menores informações sobre usos pré-padrão e comuns (isto é, POSIX) que estão fora do padrão. Harbison & Steele é bastante legível, detalhado e provavelmente mais correto que a maioria das referências. No entanto, também não é um tutorial, por isso, se você está nos estágios iniciais de aprendizado, provavelmente não é uma coisa boa de se entrar.
Michael Burr
15
Acho que o livro que você está lendo é C: The Complete Reference , de Herbert Schildt. De uma resenha deste livro ( accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm ): Não vou recomendar este livro (muitos de vocês dão muito peso às minhas opiniões), mas Não acho que mereça o mesmo opróbrio que foi legitimamente lançado em alguns de seus outros trabalhos. Como Michael diz, uma referência muito melhor é Harbison & Steele .
Alok Singhal
Meus dois centavos aqui: como charpode ser não assinado, como regra geral use um intpara ler um valor usando getchar(), que pode retornar EOF. EOFgeralmente é definido como -1ou outro valor negativo, que armazenar em um unsignednão é o que você deseja. Aqui está a declaração: extern int getchar();BTW, esta recomendação também vem do livro "C: A Reference Manual".
precisa saber é o seguinte
6
A um C referência eu confiança é a norma ISO / IEC 9899: 2011 :-)
Jeff
3
@ MaxChetrusca bons conselhos, mas raciocínio ruim: mesmo no charcaso assinado , você precisaria usar intpara armazenar o valor de retorno.
Antti Haapala

Respostas:

204

O livro está errado. O padrão não especifica se a planície charestá assinada ou não.

Na verdade, o padrão define três tipos distintos: char, signed char, e unsigned char. Se você #include <limits.h>observar CHAR_MIN, poderá descobrir se a planície charé signedou unsigned(se CHAR_MINé menor que 0 ou igual a 0), mas mesmo assim, os três tipos são distintos no que diz respeito ao padrão.

Observe que charé especial dessa maneira. Se você declarar uma variável como int100% equivalente a declará-la como signed int. Isso sempre é verdade para todos os compiladores e arquiteturas.

Alok Singhal
fonte
1
@ Alok: o mesmo não se aplica a alguns outros tipos de dados, por exemplo, intsignifica signed intsempre, certo? Além disso char, em que outros tipos de dados há a mesma confusão C?
Lazer
8
@eSKay: sim, charé o único tipo que pode ser assinado ou não assinado. inté equivalente a, signed intpor exemplo.
Alok Singhal
28
Há uma razão histérica, er, histórica para isso - no início da vida de C, o "padrão" foi revertido pelo menos duas vezes, e alguns primeiros compiladores populares terminaram de um jeito e outros do outro.
Hot Licks
9
@AlokSinghal: Também é definido pela implementação se um campo de tipo de bit inté assinado ou não.
amigos estão dizendo sobre keith thompson
@ KeithThompson obrigado pela correção. Costumo esquecer alguns detalhes sobre os tipos de campo de bits, já que não os uso muito.
Alok Singhal
67

Como Alok aponta , o padrão deixa isso para a implementação.

Para o gcc, o padrão é assinado, mas você pode modificá-lo com -funsigned-char. Nota: para o gcc no Android NDK, o padrão é não assinado . Você também pode pedir explicitamente caracteres assinados com -fsigned-char.

No MSVC, o padrão é assinado, mas você pode modificá-lo com /J.

R Samuel Klatchko
fonte
2
Interessante que a descrição de Schildt não corresponda ao comportamento da MSVC, pois seus livros geralmente são voltados para usuários da MSVC. Gostaria de saber se a Microsoft mudou o padrão em algum momento?
Michael Burr
1
Eu pensei que não era dependente do compilador, mas da plataforma. Eu pensei que char foi deixado como um terceiro tipo de "tipo de dados de caractere" para estar em conformidade com o que os sistemas da época usavam como caracteres imprimíveis.
Spidey
10
Os documentos do GCC dizem que é dependente da máquina: " Cada tipo de máquina possui um padrão para o que deve ser um caractere. É como um caracter não assinado por padrão ou como um caractere assinado por padrão. "
Deduplicator
1
Você pode fornecer uma fonte para sua nota de que, no android, o padrão é char não assinado?
Phlipsy # 22/15
1
O padrão C não faz distinção real entre compiladores, plataformas e arquiteturas de CPU. Apenas os agrupa em "implementação".
plugwash 23/11/16
35

C99 N1256 rascunho 6.2.5 / 15 "Tipos" tem a dizer sobre a assinatura do tipo char:

A implementação deve definir o caractere para ter o mesmo intervalo, representação e comportamento que o caractere assinado ou não assinado.

e em nota de rodapé:

CHAR_MIN, definido em <limits.h>, terá um dos valores 0ou SCHAR_MIN, e isso pode ser usado para distinguir as duas opções. Independentemente da escolha feita, charé um tipo separado dos outros dois e não é compatível com nenhum dos dois.

Michael Burr
fonte
7

De acordo com o livro The C Programming Language de Dennis Ritchie, que é o livro padrão de fato para ANSI C, caracteres simples assinados ou não assinados dependem da máquina, mas os caracteres imprimíveis são sempre positivos.

Ravi Rathi
fonte
9
Não é necessariamente o caso de caracteres imprimíveis serem sempre positivos. O padrão C garante que todos os membros do conjunto de caracteres de execução básica tenham valores não negativos.
Keith Thompson
7

De acordo com o padrão C, a assinatura do char simples é "implementação definida".

Em geral, os implementadores escolheram o que fosse mais eficiente para implementar em sua arquitetura. Nos sistemas x86, char geralmente é assinado. Nos sistemas de braço, geralmente não é assinado (o Apple iOS é uma exceção).

plugwash
fonte
2
@plugwash Sua resposta provavelmente foi negada porque Tim Post perdeu as chaves . Sério, porém, você não deve se preocupar com um único voto negativo, desde que tenha certeza de que sua resposta está correta (o que é neste caso). Já aconteceu comigo várias vezes para que minhas postagens sejam votadas sem motivo válido. Não se preocupe, às vezes as pessoas fazem coisas estranhas.
Donald Duck
1
Por que o char assinado é mais eficiente no x86? Alguma fonte?
22819 martinkunev
2

De acordo com "A linguagem de programação C ++", de Bjarne Stroustrup, charé "implementação definida". Pode ser signed charou unsigned chardependendo da implementação. Você pode verificar se charestá assinado ou não usando std::numeric_limits<char>::is_signed.

BoQ
fonte
9
Esta é uma pergunta C. C ++ é uma linguagem diferente e as referências em C ++ não têm relevância para C. #
MM #
1

Agora, sabíamos que o padrão deixa isso para a implementação.

Mas como verificar um tipo é signedou unsigned, como char?

Eu escrevi uma macro para fazer isso:

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

e testá-lo com gcc, clange cl. Mas não sei se é sempre seguro para outros casos.

南山 竹
fonte
O que há de errado com CHAR_MIN <0 usual (ou WCHAR_MIN <0 para wchar_t)?
Öö Tiib