1

Consider this little program:

#include <stdio.h>
int main()
{
    char c = 0xFF;
    printf("%d\n", c);

    return 0;
}

Its output is -1, as expected (considering char is signed in my system). What I'm trying to do is to make it print 255. This is of course a simplification of the real situation, where I can't just define c as unsigned.

The first possible change would be using %u as formatter instead, but the usual type promotion rules apply here, and the number is printed as 232 - 1.

So is there any way to read the signed char as unsigned before it gets promoted to an int? I could create a pointer to a unsigned char set to the address of c, and dereference it later, but not sure if this is the best approach.

sidyll
  • 57,726
  • 14
  • 108
  • 151

1 Answers1

4

c is being promoted using signed promotion rules. Cast c to unsigned to use unsigned promotion.

printf("%u\n", (unsigned char)c);

Unsigned char will be promoted to unsigned int.

Oscar Korz
  • 2,457
  • 1
  • 18
  • 18
  • I'm pretty sure you can use %d instead of %u if you want to. – David Grayson Oct 12 '11 at 16:53
  • In this situation it is ok, because the value must be [0 - 256). Generally speaking, the specifier should match the variable type. I think GCC will complain if certain warnings are switched on. – Oscar Korz Oct 12 '11 at 16:55
  • Actually I tried casting as `(unsigned int)c` and this won't work (now I'm wondering why exactly). I hadn't tried with `(unsigned char)c`. – sidyll Oct 12 '11 at 16:55
  • Ah, I guess the compiler sign extends when casting from signed char -> unsigned int. This way signed char -> unsigned int -> signed int returns the same value you started with. – Oscar Korz Oct 12 '11 at 16:57
  • Hmm, yeah, maybe the char first becomes an int (extending the sign) to then be read as unsigned. Why exactly your "_format specifier is not technically correct either_"? :-) – sidyll Oct 12 '11 at 17:01
  • 1
    I should probably use `h` (is `hh` defined in C99?) to indicate its width. However, since type promotion with varargs is guaranteed by the standard, I actually don't see the purpose of `h`. (`l` is necessary however!) – Oscar Korz Oct 12 '11 at 17:04