Chars, signed and unsigned

Parallel to signed and unsigned ints (either short or long), similarly there also exist signed and unsigned chars, both occupying one byte each, but having different ranges. To begin with it might appear strange as to how a char can have a sign. Consider the statement :

char ch = 'A' ;

Here what gets stored in ch is the binary equivalent of the ASCII value of ‘A’ (i.e. binary of 65). And if 65’s binary can be stored, then -54’s binary can also be stored (in a signed char).
 
A signed char is same as an ordinary char and has a range from -128 to +127; whereas, an unsigned char has a range from 0 to 255. Let us now see a program that illustrates this range:

Example

main( )
{
char ch = 291 ;
printf ( "\n%d %c", ch, ch ) ;
}

What output do you expect from this program? Possibly, 291 and the character corresponding to it. Well, not really. Surprised? The reason is that ch has been defined as a char, and a char cannot take a value bigger than +127. Hence when value of ch exceeds +127, an appropriate value from the other side of the range is picked up and stored in ch. This value in our case happens to be 35, hence 35 and its corresponding character #, gets printed out.

Example

#include<stdio.h>
int main() {
	char ch;
	for (ch = 0; ch <= 255; ch++)
		printf("\n%d %c", ch, ch);
	getchar();
	return 0;
}

This program should output ASCII values and their corresponding characters. Well, No! This is an indefinite loop. The reason is that ch has been defined as a char, and a char cannot take values bigger than +127. Hence when value of ch is +127 and we perform ch++ it becomes -128 instead of +128. -128 is less than 255 hence the condition is still satisfied. Here onwards ch would take values like -127, -126, -125, …. -2, -1, 0, +1, +2, … +127, -128, -127, etc. Thus the value of ch would keep oscillating between -128 to +127, thereby ensuring that the loop never gets terminated.
 
How do you overcome this difficulty? Would declaring ch as an unsigned char solve the problem? Even this would not serve the purpose since when ch reaches a value 255, ch++ would try to make it 256 which cannot be stored in an unsigned char. Thus the only alternative is to declare ch as an int. However, if we are bent upon writing the program using unsigned char, it can be done as shown below. The program is definitely less elegant, but workable all the same.

Example

#include<stdio.h>
int main() {
	unsigned char ch;
	for (ch = 0; ch <= 254; ch++)
		printf("\n%d %c", ch, ch);
	printf("\n%d %c", ch, ch);
	getchar();
	return 0;
}