функция десериализации (байтовый массив до uint32) - PullRequest
3 голосов
/ 27 мая 2011

Какой лучший способ написать функцию десериализации для преобразования массива байтов в 32-разрядное целое число без знака?

    typedef unsigned long  uint32;

    uint32 deserialize_uint32(unsigned char *buffer)
    {
        uint32 value = 0;

        value |= buffer[0] << 24;
        value |= buffer[1] << 16;
        value |= buffer[2] << 8;
        value |= buffer[3];
        return value;

    }

    unsigned char* deserialize_uint32B(unsigned char *buffer, uint32* value)
    {
        *value = 0;

        *value |= buffer[0] << 24;
        *value |= buffer[1] << 16;
        *value |= buffer[2] << 8;
        *value |= buffer[3];
        return buffer + 4;
    }

спасибо!или если есть еще лучший способ, пожалуйста, дайте мне знать .. спасибо!

Ответы [ 4 ]

2 голосов
/ 27 мая 2011

Я предпочитаю твой первый вариант второму.Или вы можете использовать параллельную обработку, имея четыре локальные переменные, которые принимают отдельные байты, смещенные на правильную величину.Затем в последней строке вы return b0shifted | b1shifted | b2shifted | b3shifted.

В любом случае, все зависит от вашего компилятора.Ваш второй вариант содержит больше операций загрузки / сохранения, поэтому в первом варианте меньше абстрактных операций.

Что касается читаемости, понятности и ясности, ваш первый вариант великолепен.Он также работает на любой странной платформе, которую вы используете (endianess, выравнивание), при условии, что CHAR_BIT == 8.

1 голос
/ 27 мая 2011

Можно сделать разумное использование кастинга, чтобы сделать это легко. Просто приведите буфер к типу, который вы хотите.

uint32 deserialize_uint32(unsigned char *buf)
{
    uint32 *x = (uint32*)buf;
    return *x;
}

unsigned char * deserialize_uint32B(unsigned char *buffer, uint32* value)
{
    *(uint32*)buffer = *value;
    return buffer;
}
0 голосов
/ 27 мая 2011

Ваш первый метод может привести к лучшему коду, потому что во втором компилятор должен предполагать, что указатели data и value могут иметь псевдоним (хотя это может быть смягчено, если компилятор может встроить функцию там, где ониспользуется.)

Если у вас есть компилятор C99, вы можете выбрать advantange uint32_t, inline, а для второго варианта restrict.

0 голосов
/ 27 мая 2011

Вы можете написать:

#include <arpa/inet.h>

uint32_t deserialize_uint32(unsigned char *buffer) {
    uint32_t res = *((uint32_t *) buffer);
    return ntohl(res);
}

unsigned char *serialize_uint32(unsigned char *buffer, uint32_t *value) {
    *((uint32_t *) buffer) = htonl(*value);
    return buffer;
}

Эта реализация гарантирует, что порядок байтов является правильным независимо от базовой архитектуры.

...