7

I expect ouput something like \9b\d9\c0... from code below, but I'm getting \ffffff9b\ffffffd9\ffffffc0\ffffff9d\53\ffffffa9\fffffff4\49\ffffffb0\ffff ffef\ffffffd9\ffffffaa\61\fffffff7\54\fffffffb. I added explicit casting to char, but it has no effect. What's going on here?

typdef struct PT {
    // ... omitted
    char GUID[16];
} PT;
PT *pt;
// ... omitted
int i;
for(i=0;i<16;i++) {
    printf("\\%02x", (char) pt->GUID[i]);
}

Edit: only casting to (unsigned char) worked for me. Compiler spits warnings on me when using %02hhx (gcc -Wall). (unsigned int) had no effect.

Ruslanas Balčiūnas
  • 7,310
  • 3
  • 24
  • 41
  • 2
    is it not like that `%x` considers `unsigned int` as argument? – Sourav Ghosh May 26 '15 at 16:23
  • The number `2` in `%02` always specifies the minimum number of digits in the field. `printf` will use the smallest implemented type, an `unsigned int` to print the value. This is the reason for the result. – Flovdis May 26 '15 at 16:26
  • 2
    Why would you *add* an explicit cast to `char` (which you already have)? I would think `(unsigned int)` would be more what you need. – WhozCraig May 26 '15 at 16:27
  • possible duplicate of [printf the last Byte of a hex value in C](http://stackoverflow.com/questions/15296032/printf-the-last-byte-of-a-hex-value-in-c) – Dmitry Grigoryev May 26 '15 at 16:38
  • Possible duplicate of [Printing hexadecimal characters in C](https://stackoverflow.com/questions/8060170/printing-hexadecimal-characters-in-c) – Ciro Santilli OurBigBook.com Nov 06 '18 at 19:45

5 Answers5

14

The reason why this is happening is that chars on your system are signed. When you pass them to functions with variable number of arguments, such as printf (outside of fixed-argument portion of the signature) chars get converted to int, and they get sign-extended in the process.

To fix this, cast the value to unsigned char:

printf("\\%02hhx", (unsigned char) pt->GUID[i]);

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
3

Use:

printf("\%02hhx", pt->GUID[i]);

Because printf() is a variadic function, its arguments are promoted to int. The hh modifier tells printf() that the type of the corresponding value is unsigned char and not int.

axiac
  • 68,258
  • 9
  • 99
  • 134
2

Cast to unsigned char instead, to avoid a leading 1 bit being interpreted as a negative value.

Jeff Ames
  • 1,424
  • 10
  • 18
2

I noticed that you were getting the F's when the number was larger than 99x.

I wrote this to test it out and discovered the hh prefix at http://www.cplusplus.com/reference/cstdio/printf/

#include "stdio.h"

char GUID[16];

int main() {
int i;
for(i=0;i<16;i++) {
    GUID[i]=i*i;
}
for(i=0;i<16;i++) {
    printf("\\%02.2hhx\n", GUID[i]);
}
return 0;
}
Rob Fagen
  • 774
  • 1
  • 8
  • 24
0

Use a small own implementation to solve this problem on all platforms:

char hex[] = "0123456789abcdef";

void printHex(unsigned char byte) {
    printf("%c%c", hex[byte>>4], hex[byte&0xf]);
}
Flovdis
  • 2,945
  • 26
  • 49