What does "representable" mean in C11?
c, c11, language-lawyer
Solution
Under the assumption that char is signed then this would be undefined behavior, otherwise it is well defined since `CHAR_MIN` would have the value `0`. It is easier to see the intention and meaning of:
the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF
if we read section `7.4` Character handling <ctype.h> from the Rationale for International Standard—Programming Languages—C which says (emphasis mine going forward):
Since these functions are often used primarily as macros, their domain is restricted to the small positive integers representable in an unsigned char, plus the value of EOF. EOF is traditionally -1, but may be any negative integer, and hence distinguishable from any valid character code. These macros may thus be efficiently implemented by using the argument as an index into a small array of attributes.
So valid values are:
- Positive integers that can fit into unsigned char
- `EOF` which is some implementation defined negative number
Even though this is C99 rationale since the particular wording you are referring to does not change from C99 to C11 and so the rationale still fits.
We can also find why the interface uses int as an argument as opposed to char, from section `7.1.4` Use of library functions, it says:
All library prototypes are specified in terms of the “widened” types an argument formerly declared as char is now written as int. This ensures that most library functions can be called with or without a prototype in scope, thus maintaining backwards compatibility with pre-C89 code. Note, however, that since functions like printf and scanf use variable-length argument lists, they must be called in the scope of a prototype.
Problem
According to C11 WG14 draft version N1570: The header `<ctype.h>` declares several functions useful for classifying and mapping characters. In all cases the argument is an `int`, the value of which shall be representable as an `unsigned char` or shall equal the value of the macro `EOF`. If the argument has any other value, the behavior is undefined. Is it undefined behaviour?: ``` #include <ctype.h> #include <limits.h> #include <stdlib.h> int main(void) { char c = CHAR_MIN; /* let assume that char is signed and CHAR_MIN < 0 */ return isspace(c) ? EXIT_FAILURE : EXIT_SUCCESS; } ``` Does the standard allow to pass `char` to `isspace()` (`char` to `int`)? In other words, is `char` after conversion to `int` representable as an `unsigned char`? Here's how wiktionary defines "representable": Capable of being represented. Is `char` capable of being represented as `unsigned char`? Yes. §6.2.6.1/4: Values stored in non-bit-field objects of any other object type consist of n `×` `CHAR_BIT` bits, where n is the size of an object of that type, in bytes. The value may be copied into an object of type unsigned char [n] (e.g., by memcpy); the resulting set of bytes is called the object representation of the value. `sizeof(char) == 1` therefore its object representation is `unsigned char[1]` i.e., `char` is capable of being represented as an `unsigned char`. Where am I wrong? Concrete example, I can represent `[-2, -1, 0, 1]` as `[0, 1, 2, 3]`. If I can't then why? Related: According to §6.3.1.3 `isspace((unsigned char)c)` is portable if `INT_MAX >= UCHAR_MAX` otherwise it is implementation-defined.