173
votes

In the book "Complete Reference of C" it is mentioned that char is by default unsigned.

But I am trying to verify this with GCC as well as Visual Studio. It is taking it as signed by default.

Which one is correct?

6
The one C reference book I trust is Harbison & Steele's "C: A Reference Manual" (careferencemanual.com). Of course the standard is the final word, but it's not very readable and only gives the slightest information on pre-standard and common (ie., POSIX) uses that are outside the standard. Harbison & Steele is quite readable, detailed and probably more correct than most references. However it also isn't a tutorial, so if you're in the initial stages of learning it's probably not a great thing to jump into.Michael Burr
I think the book you are reading is C: The Complete Reference, by Herbert Schildt. From a review of this book (accu.informika.ru/accu/bookreviews/public/reviews/c/c002173.htm): I am not going to recommend this book (too many of you give too much weight to my opinions) but I do not think it deserves the same opprobrium that has been legitimately thrown at some of his other work. As Michael says, a much better reference is Harbison & Steele.Alok Singhal
My two cents here: Because char can be unsigned, as a rule of thumb use an int to read a value using getchar(), which might return EOF. EOF is usually defined as -1 or other negative value, which storing in an unsigned is not what you want. Here's the declaration: extern int getchar(); BTW, this recommendation comes also from "C: A Reference Manual" book.Maxim Chetrusca
The one C reference I trust is ISO/IEC 9899:2011 :-)Jeff Hammond
@MaxChetrusca good advice but bad rationale: even on the signed char case, you'd have to use int to store the return value.Antti Haapala

6 Answers

222
votes

The book is wrong. The standard does not specify if plain char is signed or unsigned.

In fact, the standard defines three distinct types: char, signed char, and unsigned char. If you #include <limits.h> and then look at CHAR_MIN, you can find out if plain char is signed or unsigned (if CHAR_MIN is less than 0 or equal to 0), but even then, the three types are distinct as far as the standard is concerned.

Do note that char is special in this way. If you declare a variable as int it is 100% equivalent to declaring it as signed int. This is always true for all compilers and architectures.

68
votes

As Alok points out, the standard leaves that up to the implementation.

For gcc, the default is signed, but you can modify that with -funsigned-char. note: for gcc in Android NDK, the default is unsigned. You can also explicitly ask for signed characters with -fsigned-char.

On MSVC, the default is signed but you can modify that with /J.

37
votes

C99 N1256 draft 6.2.5/15 "Types" has this to say about the signed-ness of type char:

The implementation shall define char to have the same range, representation, and behavior as either signed char or unsigned char.

and in a footnote:

CHAR_MIN, defined in <limits.h>, will have one of the values 0 or SCHAR_MIN, and this can be used to distinguish the two options. Irrespective of the choice made, char is a separate type from the other two and is not compatible with either.

8
votes

According to The C Programming Language book by Dennis Ritchie which is the de-facto standard book for ANSI C, plain chars either signed or unsigned are machine dependent, but printable characters are always positive.

8
votes

According to the C standard the signedness of plain char is "implementation defined".

In general implementors chose whichever was more efficient to implement on their architecture. On x86 systems char is generally signed. On arm systems it is generally unsigned (Apple iOS is an exception).

1
votes

Now, we known the standard leaves that up to the implementation.

But how to check a type is signed or unsigned, such as char?

I wrote a macro to do this:

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

and test it with gcc, clang, and cl. But I do not sure it's always safe for other cases.