ID Number: Q69344
5.00 5.10 6.00 6.00a 7.00 | 5.10 6.00 6.00a
MS-DOS | OS/2
Summary:
In Microsoft C versions 5.1, 6.0, 6.0a, 6.0ax, and C/C++ version 7.0,
when trying to display a signed char in two-digit hexadecimal format, as
follows:
char hex_byte = 0x80;
printf( "The Hex value is %X", hex_byte);
four digits will be displayed if the char has a value of 0x80 to 0xFF
because of promotion of the char to a signed int. The %x and %X
specifiers designate an unsigned hex integer, but because leading 0s
(zeros) are dropped, values in the range of 0 to 127 produce the
desired two digits. See the sample code below.
To preserve the two-digit display for all possible values, typecast
the char to an unsigned char in the printf() argument list, as shown
below:
printf( "The Hex value is %X", (unsigned char)hex_byte);
Another way to achieve this, if sign is of no consequence, is to
declare the variables as unsigned char.
More Information:
For ANSI compliance, the compiler promotes all char arguments to
signed int. If the type is signed char, then the value will be
sign-extended. Thus, the int will be negative if the left-most bit of
the char was set, resulting in a different value for the int. When an
unsigned char is promoted, a 0 (zero) is placed in the high byte so
that the value is retained.
This promotion may also cause problems with comparisons of signed and
unsigned chars. This situation, unlike the printf() situation, will
produce a C4018 (signed/unsigned mismatch) warning at warning level 3
and above, beginning with C version 6.0.
This behavior is also observed in QuickC versions 2.0 and 2.5 and
QuickC with QuickAssembler versions 2.01 and 2.51.
Sample Code
-----------
/* Compile options needed: none
*/
#include <stdio.h>
void main( void)
{
char goo = 127;
char foo = 128;
printf( "goo = %X\n", goo); /* yields "7F" */
printf( "foo = %X\n", foo); /* yields "FF80" */
/* correct way to represent the char as two hex digits "80" */
printf( "foo = %X\n", (unsigned char)foo);
}
Additional reference words: 2.00 2.50 5.10 6.00 6.00a 6.00ax 7.00