INFO: Promotion of char to int May Add Two Hex Digits in printf

Last reviewed: September 4, 1997
Article ID: Q69344

The information in this article applies to:
  • Microsoft C for MS-DOS, versions 6.0, 6.0a, 6.0ax
  • Microsoft C for OS/2, versions 6.0, 6.0a
  • Microsoft C/C++ for MS-DOS, version 7.0
  • Microsoft Visual C++ for Windows, versions 1.0, 1.5
  • Microsoft Visual C++ 32-bit Edition, versions 1.0, 2.0, 4.0, 5.0

SUMMARY

When you try to display a signed character in two-digit hexadecimal format as follows:

   char hex_byte = 0x80;
   printf( "The Hex value is %X", hex_byte);

four digits are displayed if the character has a value of 0x80 to 0xFF because of promotion of the character to a signed int. Under Windows NT, eight digits will be displayed because of the integer size difference. The %x and %X specifiers designate an unsigned hexadecimal 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 character to an unsigned character 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 character.

MORE INFORMATION

For ANSI compliance, the compiler promotes all character arguments to signed int. If the type is signed character, then the value will be sign- extended. Thus, the int will be negative if the left-most bit of the character was set, resulting in a different value for the int. When an unsigned character 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 characters. 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.

Sample Code

   /* Compile options needed: none
   */

   #include <stdio.h>

   void main( void)
   {
      char goo = 127;
      char myvar = 128;

      printf( "goo = %X\n",   goo); /* yields "7F" */
      printf( "myvar = %X\n",   myvar); /* yields "FF80" or "FFFFFF80"*/

      /* Correct way to represent the char as two hex digits "80". */
      printf( "myvar = %X\n",   (unsigned char)myvar);
   }


Additional query words: conversion
Keywords : CLngIss kbcode
Version : MS-DOS:6.0,6.00a,7.0; OS/2:6.0,6.00a; WINDOWS:1.0,1.5; WINDOWS NT:1.0,2.0,4.0,5.0
Platform : MS-DOS NT OS/2 WINDOWS
Issue type : kbinfo


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: September 4, 1997
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.