Firstly, remember that chars are just little integers, usually byte-sized. So on my system (and probably yours, too), these are the sizes of the basic integer types:
guaranteed by the
standard to be
bytes bits at least
char 1 8 1
short 2 16 2
int 4 32 2
long 8 64 4
long long 8 64 8 |
All the basic integer types except char are assumed to be signed if you don't say "signed" or "unsigned". E.g., signed int is exactly the same as int (so there is never really a reason to say signed int, and signed int is not a distince type, just a synonym for int). unsigned int is the unsigned version of int.
However, for char it's different. Because of possible differences between different computer systems, it may be best to have char (the plain char type, without "signed" or "unsigned" in front of it) as equivalent to an unsigned char instead of signed char. Even if char happens to be signed on your system (as it is on mine), to write portable code you can't assume that it's signed.
Therefore there is a unique meaning to saying "signed char" (unlike saying "signed int" which is identical to saying "int"), so chars actually have 3 distinct types while short, int, long, long long only have 2 distinct types. That is, the type "char" is different from the type "signed char", even if it's actually the same!
If you convert the char to an int you can see whether char is signed or unsigned on your system:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
#include <iostream>
int main() {
char ch = 0x7f; // highest 7-bit value 0111 111 (which is highest positive value if char is signed)
char ch2 = ch;
++ch2; // overflow the positive value of signed char (if char is signed char)
// Technically the above is "undefined behavior" so according to the standard
// we can't rely on what happens. But the usual thing is for the value
// to "wrap around" to the most negative value.
// if ch2 is negative then it overflowed and char is signed char
std::cout << int(ch) << ", " << int(ch2) << '\n';
}
|