2

Following on this question How to convert a string to hex and vice versa in c??

I run the following code:

#include <stdio.h>

int main (int argc, char *argv[])
{
    char str[] = { 0x58, 0x01, 0x02, 0x20, 0x22, 0x00, 0xC5};
    char hex[32] = {0}, hex2[32] = {0};

    for (int i = 0; i < sizeof(str); i++) {
        sprintf(hex + i*2, "%02X", str[i]);
    }

    for (int i = 0; i < sizeof(str); i++) {
        sprintf(hex2 + i*2, "%02X", str[i] & 0xff);
    }

    printf("hex = %s\nhex2 = %s\n", hex, hex2);
    return 0;
}

I get this result:

hex = 580102202200FFFFFFC5
hex2 = 580102202200C5

I wonder why there is more FFFFFF without 0xFF?

Orivee
  • 23
  • 5
  • Change `char str[] = ...` to `unsigned char str[] = ...` and the extra F's will disappear. Now, to really learn, you work out what difference that makes. – Fe2O3 Sep 29 '22 at 06:14
  • https://stackoverflow.com/questions/2054939/is-char-signed-or-unsigned-by-default – Lundin Sep 29 '22 at 06:40

1 Answers1

3

There are many small pieces to the puzzle that needs to be put together.

To begin with it's implementation-defined if char is signed or unsigned.

If it's signed, then because of the common two's complement the value 0xc5 will actually be negative (it will be the decimal value -59).

And when a small integer type (like char) is used as an argument to a variable-argument function like sprintf, then it will be promoted to int. If the type is signed and the value is negative, it will be sign extended. So assuming the common 32-bit int, the signed and negative value 0xc5 will be promoted and sign-extended to 0xffffffc5.

To solve this problem, the simplest solution is to simply use an explicit unsigned type like uint8_t (which basically is an alias for unsigned char).

Besides that I also recommend you use the hh format type prefix to explicitly say that the argument is a byte.

Put together change to

uint8_t str[] = { 0x58, 0x01, 0x02, 0x20, 0x22, 0x00, 0xC5};

and

sprintf(hex + i*2, "%02hhX", str[i]);

As for the difference made by str[i] & 0xff, it's because then you mask out the top 24 bits of the int value. So 0xffffffc5 & 0xff becomes 0x000000c5.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621