I always knew I had signed values when I used int
or long
, char
, short
, etc. in C and C++ development. By the way, depending on the compiler or OS, what happens when the default signedness of these types becomes unsigned? I'm inquiring because I've never seen a reference to this in a paper or a book, and I don't know it.
Types short
, int
, long
and long long
are all signed unless explicitly qualified as unsigned
. Note that short
and long
are actually qualifiers themselves and the type int
is implicit if omitted.
Type char
is special: it is different from type signed char
, which obviously is signed and from type unsigned char
, which is not. Depending on the platform and compiler settings, type char
may be signed or unsigned. You can test this by comparing the value of the macro CHAR_MIN
defined in <limits.h>
to 0
or by casting -1
as (char)
and testing if it stays negative.
#include <limits.h>
#include <stdio.h>
int main(void) {
if ((char)-1 < 0) {
/* most common case */
printf("char is signed, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
} else
if (sizeof(char) == sizeof(int)) {
/* corner case, for some DSP systems */
/* char type is the same as unsigned int */
printf("char is unsigned, range is %u..%u\n", CHAR_MIN, CHAR_MAX);
} else {
/* common case, enabled with -funsigned-char for gcc and clang */
/* char values and constants will promote to int */
printf("char is unsigned, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
}
return 0;
}
Note that you cannot use the above tests for preprocessing, but the constants defined in <limits.h>
can be used in preprocessor expressions:
#include <limits.h>
#include <stdio.h>
int main(void) {
#if CHAR_MIN < 0
printf("char is signed, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
#elif CHAR_MAX == UINT_MAX
printf("char is unsigned, range is %u..%u\n", CHAR_MIN, CHAR_MAX);
#else
printf("char is unsigned, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
#endif
return 0;
}
This also works in C++, but there is a more idiomatic way to test it using std::is_signed_v<char>
.