Портативный способ печати шестнадцатеричных значений с помощью sprintf

У меня были некоторые проблемы с преобразованием двоичного кода в (печатаемый) шестнадцатеричный. Я нашел функциональный (для своей системы) способ написания кода, но мне нужно знать, переносим ли он на все системы (ОС и оборудование).

Итак, это моя функция (попытка построить UUID из фрагмента двоичного текста):

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;
}

Я понял, что из-за знакового расширения мои значения плохо печатаются, если я использую char вместо unsigned char (С++ считывает двоичный файл и преобразует в шестнадцатеричный). Принято и изменено соответственно.

Но я встречал и другие варианты этого: преобразование из двоичного hex в C, и я действительно потерялся. В фрагменте кода раскрутки:

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

Я не понял, почему, хотя массив представляет собой unsigned char (как определено в исходном опубликованном коде тем, кто задал вопрос), необходимо приведение к unsigned int, а также < strong>побитовое И для байта, который нужно преобразовать...

Итак, поскольку я не очень хорошо понял, что такое расширение знака, можете ли вы сказать мне, по крайней мере, будет ли написанный мной фрагмент кода работать на всех системах?


person simm    schedule 20.03.2014    source источник
comment
Я не верю в том, что такое приведение технически необходимо, так как параметр в любом случае будет автоматически повышаться. Битовая маска также не нужна. (Не ответ, потому что я не на 100% уверен в актерском составе.)   -  person TypeIA    schedule 20.03.2014
comment
Если вы уже используете С++, зачем вообще использовать snprintf()? Любой код C++ для вывода ваших материалов с использованием std::ostream будет переносимым без проблем.   -  person πάντα ῥεῖ    schedule 20.03.2014
comment
unsigned char будет повышен до int (если только sizeof(char) == sizeof(int)...), а не до unsigned int, а спецификатор формата %x говорит, что ему нужен unsigned int.   -  person Simple    schedule 20.03.2014
comment
Вы можете использовать спецификатор длины hh: snprintf( h, 3, "%02hhx", text[i] );   -  person Johnny Mopp    schedule 20.03.2014
comment
Если buffer определяется как unsigned char buffer[N], то ни приведение, ни побитовое И с 0xff не нужны. Если buffer определяется как char buffer[N], вам нужно привести к unsigned char или вам нужно выполнить побитовое И с 0xff; если вы делаете оба, это перебор.   -  person Jabberwocky    schedule 20.03.2014


Ответы (1)


поскольку printf не является типобезопасным, он ожидает для каждого спецификатора форматирования аргумент специального размера. вот почему вы должны привести свой символьный аргумент к unsigned int, если вы используете какой-либо символ форматирования, который ожидает тип с размером int.

Для спецификатора "%x" требуется целое число без знака.

person vlad_tepesch    schedule 20.03.2014