¿Por qué las funciones ctype toman int pero quieren un char / EOF sin firma?

Estoy usando gcc (Ubuntu / Linaro 4.6.1-9ubuntu3) 4.6.1

La página del isalnum() para isalnum() dice:

 SYNOPSIS #include  int isalnum(int c); 

Sin embargo, también dice:

Estas funciones verifican si c, que debe tener el valor de un carácter sin signo o EOF, …

Descubrí que isalnum() explotará para valores int positivos (o negativos) muy grandes (pero maneja todos short int valores short int ).

¿La página de manual que dice que se pasó el int debe tener el valor de un unsigned char porque los escritores de la biblioteca C se reservan el derecho de implementar isalnum() de una manera que no manejará todos los valores del int sin explotar?

La norma C dice tanto …

En ISO / IEC 9899: 1999 (el antiguo estándar C), dice:

§7.4 Manejo de personajes

El encabezado declara varias funciones útiles para clasificar y mapear caracteres. En todos los casos, el argumento es un int, cuyo valor será representable como un carácter sin signo o será igual al valor de la macro EOF. Si el argumento tiene algún otro valor, el comportamiento no está definido.

( He omitido una nota a pie de página ) . Tanto el C89 como el C11 dicen mucho lo mismo.

Una implementación común es usar un array offset por 1, una variación del tema de:

 int _CtypeBits[257] = { ... }; #define isalpha(c) (_Ctype_bits[(c)+1]&_ALPHA); 

Mientras que c esté en el rango de enteros que puede almacenar un personaje unsigned char (y hay 8 bits por carácter, EOF es -1 , y la inicialización es correcta), entonces esto funciona a la perfección. Tenga en cuenta que la expansión de macros solo usa el argumento una vez, que es otro requisito de la norma. Pero si pasa valores aleatorios fuera del rango estipulado, tendrá acceso a memoria aleatoria (o, al menos, memoria que no se inicializa para contener la información correcta).