fix dubious char signedness check in limits.h
authorRich Felker <dalias@aerifal.cx>
Tue, 28 Aug 2018 17:54:50 +0000 (13:54 -0400)
committerRich Felker <dalias@aerifal.cx>
Tue, 28 Aug 2018 17:54:50 +0000 (13:54 -0400)
commit 201995f382cc698ae19289623cc06a70048ffe7b introduced a hack
utilizing the signedness of character constants at the preprocessor
level to avoid depending on the gcc-specific __CHAR_UNSIGNED__ predef.
while this trick works on gcc and presumably other compilers being
used, it's not clear that the behavior it depends on is actually
conforming. C11 6.4.4.4 ¶10 defines character constants as having type
int, and 6.10.1 ¶4 defines preprocessor #if arithmetic to take place
in intmax_t or uintmax_t, depending on the signedness of the integer
operand types, and it is specified that "this includes interpreting
character constants".

if character literals had type char and just promoted to int, it would
be clear that when char is unsigned they should behave as uintmax_t at
the preprocessor level. however, as written the text of the standard
seems to require that character constants always behave as intmax_t,
corresponding to int, at the preprocessor level.

since there is a good deal of ambiguity about the correct behavior and
a risk that compilers will disagree or that an interpretation may
mandate a change in the behavior, do not rely on it for defining
CHAR_MIN and CHAR_MAX correctly. instead, use the signedness of the
value (as opposed to the type) of '\xff', which will be positive if
and only if plain char is unsigned. this behavior is clearly
specified, and the specific case '\xff' is even used in an example,
under 6.4.4.4 of the standard.

include/limits.h

index ab163a22accd727594796afbac9aa64689bf26d0..02c2139d27d6e1f80446f0d7d1c2642ac317d71a 100644 (file)
@@ -9,7 +9,7 @@
 
 /* Support signed or unsigned plain-char */
 
-#if '\0'-1 > 0
+#if '\xff' > 0
 #define CHAR_MIN 0
 #define CHAR_MAX 255
 #else