Объединение массива uint8 с ошибкой uint64

Я пробую этот код, где я сначала разбиваю число uint64 на массив uint8, а затем объединяю указанный массив обратно в исходный номер.

Однако, когда я пытаюсь распечатать число out, кажется, что оно возвращает максимальное значение uint64.

uint8 buf[8];
uint64 test = 123456789012;
uint64 out = 0;

Uint64toUint8Arr(buf, test, 0);
out = Uint8ArrtoUint64(buf, 0);
std::cout << "out is " << out << std::endl;

где мои функции определены как:

void Uint64toUint8Arr (uint8* buf, uint64 var, uint32 lowest_pos)
{
    buf[lowest_pos]     =   (var & 0x00000000000000FF) >> 0 ;
    buf[lowest_pos+1]   =   (var & 0x000000000000FF00) >> 8 ;
    buf[lowest_pos+2]   =   (var & 0x0000000000FF0000) >> 16 ;
    buf[lowest_pos+3]   =   (var & 0x00000000FF000000) >> 24 ;
    buf[lowest_pos+4]   =   (var & 0x000000FF00000000) >> 32 ;
    buf[lowest_pos+5]   =   (var & 0x0000FF0000000000) >> 40 ;
    buf[lowest_pos+6]   =   (var & 0x00FF000000000000) >> 48 ;
    buf[lowest_pos+7]   =   (var & 0xFF00000000000000) >> 56 ;
}

uint64 Uint8ArrtoUint64 (uint8* var, uint32 lowest_pos)
{
    return  (var[lowest_pos+7] << 56) | 
            (var[lowest_pos+6] << 48) |
            (var[lowest_pos+5] << 40) | 
            (var[lowest_pos+4] << 32) |
            (var[lowest_pos+3] << 24) | 
            (var[lowest_pos+2] << 16) |
            (var[lowest_pos+1] << 8)  | 
            (var[lowest_pos]   << 0);
}

Мой вопрос в том, что я ошибся, разделив или объединив номер uint64? Я сделал аналогичную функцию для типа uint32, и все было в порядке.


person John Tan    schedule 04.09.2014    source источник
comment
Примечание. Сложно выполнить std::cout << "out is " << out << std::endl; в C.   -  person chux - Reinstate Monica    schedule 04.09.2014


Ответы (1)


Проблема в том, что вы сдвигаете uint8 в функции Uint8ArrtoUint64() более чем на 8 бит. Насколько я знаю, это неопределенное поведение. В любом случае, возвращаемое значение равно uint8, так что вы используете "ИЛИ" восемь раз по восемь чисел uint8 и, наконец, у вас есть только число uint8, а не uint64! Вам нужно сначала перевести их на uint64, а затем на Shift.

uint64 Uint8ArrtoUint64 (uint8* var, uint32 lowest_pos)
{
    return  (((uint64)var[lowest_pos+7]) << 56) | 
            (((uint64)var[lowest_pos+6]) << 48) |
            (((uint64)var[lowest_pos+5]) << 40) | 
            (((uint64)var[lowest_pos+4]) << 32) |
            (((uint64)var[lowest_pos+3]) << 24) | 
            (((uint64)var[lowest_pos+2]) << 16) |
            (((uint64)var[lowest_pos+1]) << 8)  | 
            (((uint64)var[lowest_pos])   << 0);
}

Примечание. Как @interjay отметил, операция сдвига на uint8 фактически даст нам uint32. Я не уверен в этом, но в любом случае лучше упомянуть об этом.

person Eldar Dordzhiev    schedule 04.09.2014
comment
Фактически uint8s будут повышены до int, что, вероятно, составляет 32 бита. Это объясняет, почему 32-битная версия работает, а 64-битная версия требует приведения типов. - person interjay; 04.09.2014