http://groups-beta.google.com/group/...a8ff53f0?hl=en
Code:
I have no idea when the last discussion was, but yes, something like
this is a good idea. It applies to all the <ctype.h> functions. The
problem is that their domain -- the set of values they take -- is
{EOF, [0..UCHAR_MAX]}. That is, toupper(EOF) is defined; toupper(0)
is defined; toupper(1), toupper(2), toupper(3), etc., are defined;
toupper(128) through toupper(255) are all defined; and if UCHAR_MAX
exceeds 255, additional toupper()s are defined.
On the other hand, unless EOF is -40, toupper(-40) is *not* defined.
If plain "char" is signed, and if "char *p" happens to point to a
plain "char" that has a value of -40, then:
toupper(*p)
is *not* defined. (It gives rise to the dreaded "undefined behavior".)
You can write either of these:
toupper((unsigned char)*p)
toupper(*(unsigned char *)p)
which have different meanings on one's complement and sign-and-magnitude
systems. So, which one you should write depends on what is in the
memory to which "p" points.
All "normal" characters are nonnegative, so toupper('a') is definitely
'A', whether 'a' is 0x61 (ASCII) or 0x81 (EBCDIC) or something else
entirely. (This implies that, on 8-bit EBCDIC systems such as IBM
mainframes, plain "char" must in fact be unsigned.) So if "p"
points to normal text, the undefined-behavior aspect of touppper(*p)
will not rear its ugly head. Unfortunately, all *that* really means
is that bugs tend to get past testing, and produce undefined behavior
when someone in Europe runs ISO-Latin-1 text through the program.
[edit]http://www.stanford.edu/~blp/writing...type-cast.html
Of course, if you store the return value of one of these function in a char object, then pass the char, the cast becomes necessary again.
As in,
Code:
#include <stdio.h>
#include <ctype.h>
int myisprint(int value)
{
if ( value < 0 )
{
puts("Bzzzt!");
return 0;
}
return isprint(value);
}
/* embedded nasty character: ö */
int main(void)
{
char buffer[1024];
int i, j;
for ( i = 0; i < 1024; ++i )
{
int c = getchar();
if ( c == EOF )
{
break;
}
buffer[i] = c;
}
for ( j = 0; j < i; ++j )
{
if ( myisprint(buffer[j]) )
{
/* putchar(buffer[j]); */
}
}
return 0;
}
/* my output
C:\Test>test < test.c
Bzzzt!
*/