pete said:
I don't think so.
If you were to output the value of (c) using fputc,
then the return value of the function call would be
((int)(unsigned char)c).
Th value of (c) "converted to unsigned char" is ((unsigned char)c).
That's right but the parameter c is of type 'int', not type
char. Where did this 'int' value come from? Presumably it
came from (among other places) an input function like 'fgetc()'
(see below).
N869
4.9.7.3 The fputc function
Synopsis
#include <stdio.h>
int fputc(int c, FILE *stream);
Description
The fputc function writes the character specified by c
(converted to an unsigned char ) ...
I no longer use N869, but looking at C99 (the wording is basically
unchanged from C90) for fgetc(), the description says fgetc() reads
the next character "as an 'unsigned char' converted to an 'int'"
(the single quotes designate C program text). Note especially
the first word there, "as".
I take this phrase to mean the character object is read _as_ an
'unsigned char' (eg, through an 'unsigned char *' pointer), rather
than being _converted_ to 'unsigned char' (eg, through a 'char *'
pointer and then casting that value to 'unsigned char').
Otherwise, this sentence would have said it reads the next
character "as a 'char' converted to an 'unsigned char' converted
to an 'int'. But it doesn't say that.
Presumably the "ctype.h" functions are meant to work correctly
on values returned by fgetc(), etc.
Also, isalpha also has to be able to work with arguments
which may be constant expressions that don't have addresses.
Given
#define NEG_A ('A' - 1 - (unsigned char)-1)
then isalpha ((unsigned char)NEG_A) should return nonzero
and putchar((unsigned char)NEG_A) should return ('A')
That's true but irrelevant to the point under discussion -- the
expression here doesn't involve characters with negative values.
The example I gave (with a variable 'char c') was just an example
for when there is a variable present. More generally, if you want a
function like 'isalpha()' but which takes a 'char' valued argument,
this can (and, I would argue, should) be done as follows
#define char_isalpha(c) \
isalpha( (int) (union {char c; unsigned char u;}){ c }.u )
to match the description of how fgetc() works.