Characters and integers are rather tightly knit in C.
When you receive a character from an input stream, it must be able to represent every single character plus the end-of-file symbol.
That means a char
type won't be big enough so they use a wider type.
The C99 rationale document states:
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.
The standard itself has this to say:
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.