2

I've had some trouble with binary-to-(printable)hexa conversions. I've reached a functional (for my system) way of writing the code, but I need to know if it is portable on all systems (OS & hardware).

So this is my function (trying to construct a UUID from a piece of binary text):

int extractInfo( unsigned char * text )
{
    char h[3];
    int i;

    this->str.append( "urn:uuid:" );
    for( i = 56; i < 72; i++ )
    {
        ret = snprintf( h, 3, "%02x", text[i] );
        if( ret != 2 )
            return 1;
        this->str.append( h );
        if( i == 59 || i == 61 || i == 63 || i == 65 )
            this->str.append( "-" );
    }

    return 0;
}

I understood that because of the sign extension my values are not printed well if I use char instead of unsigned char (C++ read binary file and convert to hex). Accepted and modified respectively.

But I've encountered more variants of doing this: Conversion from binary file to hex in C, and I am really lost. In unwind's piece of code:

sprintf(hex, "%02x", (unsigned int) buffer[0] & 0xff);

I did not understood why, although the array is unsigned char (as defined in the original posted code, by the one who asked the question), a cast to an unsigned int is needed, and also a bitwise AND on the byte to be converted...

So, as I did not understood very well the sign-extension thing, can you tell me at least if the piece of code I wrote will work on all systems?

Community
  • 1
  • 1
simm
  • 33
  • 4
  • 2
    I don't *believe* the cast is technically needed, as the parameter will automatically be promoted anyway. The bit mask is also not needed. (Not an answer because I'm not 100% positive about the cast.) – TypeIA Mar 20 '14 at 14:18
  • 1
    If you're already using c++, why to use `snprintf()` at all? Any c++ code to output your stuff using a `std::ostream` will be portable whithout problems. – πάντα ῥεῖ Mar 20 '14 at 14:22
  • `unsigned char` will be promoted to `int` (unless `sizeof(char) == sizeof(int)`...), not `unsigned int`, and the `%x` format specifier says it needs an `unsigned int`. – Simple Mar 20 '14 at 14:30
  • 2
    You can use the hh length specifier: `snprintf( h, 3, "%02hhx", text[i] );` – 001 Mar 20 '14 at 14:32
  • 1
    If `buffer` is defined as `unsigned char buffer[N]` then neither the cast nor the bitwise AND with 0xff is necessary. If `buffer` is defined as `char buffer[N]` then you need to cast to `unsigned char` or you need to do the bitwise AND with 0xff; if you do both, it's overkill. – Jabberwocky Mar 20 '14 at 14:34

1 Answers1

1

since printf is not typesafe it expects for each formatting specifier a special sized argument. thatswhy you have to cast your character argument to unsigned int if you use some formatting character that expects an int-sized type.

The "%x" specifier requires an unsigned int.

vlad_tepesch
  • 6,681
  • 1
  • 38
  • 80