Сериализация длинного массива (в C) - PullRequest
2 голосов
/ 02 октября 2008

в программе на Си у меня есть длинный *, который я хочу сериализовать (таким образом, конвертируя в символы). Long не умещается в одном символе, и его размер зависит от процессора (может быть 4 байта или 8 байтов).

Есть хороший способ сделать сериализацию и десериализацию?

Ответы [ 6 ]

3 голосов
/ 08 октября 2008

Это портативно, но далеко не так неэффективно, как использование printf / scanf

void longtochar(char *buffer, unsigned long number) {
    int i;
    for (i=0; i<sizeof(long); i++) {
        buffer[i] = number & 0xFF; // place bottom 8 bits in char
        number = number >> 8; // shift down remaining bits
    }
    return; // the long is now stored in the first few (2,4,or 8) bytes of buffer
}

И снова распаковать его (при условии, что длина одного размера)

long chartolong(char *buffer) {
    long number = 0;
    int i;
    for (i=sizeof(long)-1; i>=0; i--) {
        number = number << 8; // left shift bits in long already
        number += buffer[i]; // add in bottom 8 bits
    }
    return number;
}

Обратите внимание на БОЛЬШОЕ предположение, что long - это одна и та же длина в обеих системах. Безопаснее всего сделать #include и использовать предоставляемые им типы (uint32_t или uint16_t).

Кроме того, мой код имеет длинную строку без знака. Сейчас у меня нет доступа к компилятору C, поэтому я не могу подтвердить, будет ли он работать со знаком целыми числами. Если мне не изменяет память, ее поведение может быть неопределенным (хотя это может не иметь значения, как я справлюсь с этим).

2 голосов
/ 02 октября 2008

Вам не нужно сериализовать как символы - вы можете написать как longs (в файл). Чтобы сериализовать в массив символов, в начале необходимо указать байт, чтобы указать размер int и порядок следования байтов - это понадобится вам позже.

т.е.

char *p = &long_array[0];

Чтобы получить доступ к длинному массиву как char просто приведите его - и умножьте длину массива на sizeof (long), чтобы получить размер в символах.

Простой пример иллюстрирует это:

#include <stdio.h>

main()
{
    int aaa[10];
    int i;
    char *p;

    for(i=0;i<sizeof(aaa)/sizeof(aaa[0]);i++)
    {
        aaa[i] = i;
        printf ("setting aaa[%d] = %8x\n",i,aaa[i]);
    }

    aaa[9] = 0xaabbccdd;

    printf ("sizeof aaa (bytes) :%d\n",sizeof(aaa));
    printf ("each element of aaa bytes :%d\n",sizeof(aaa[0]));

    p = (char*) aaa;
    for(i=0;i<sizeof(aaa);i++)
        printf ("%d: %8x\n",i,(unsigned char)p[i]);
}
2 голосов
/ 02 октября 2008

Вы, вероятно, решаете не ту проблему. Вам следует сериализовать до фиксированного размера int, используя, например, int32_t. Возможно, вы захотите использовать этот тип фиксированного размера во всей вашей программе, или у вас возникнут проблемы, когда 64-битная программа не может сохранить файл меньшего размера (или использовать int64_t).

Если вы знаете, что вам никогда не придется загружать 64-битные сохранения на 32-битной платформе, не беспокойтесь. Просто запишите sizeof (long) байтов в файл и прочитайте обратно sizeof (long) байтов. Но поставьте флаг в начале ваших данных, который указывает исходную платформу, чтобы избежать ошибок.

1 голос
/ 02 октября 2008

В C вы можете получить размер длинной с

sizeof(long)

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

1 голос
/ 02 октября 2008
long * longs;

// ...

int numChars = numLongs * sizeof(long);
char* longsAsChars = (char*) longs;
char* chars = malloc(numChars);
memcpy(chars, longsAsChars, numChars);
0 голосов
/ 02 октября 2008

Если вы создадите указатель на символ, указывающий на начало длинного массива, при увеличении «массива» символа вы будете получать 8 битов за раз. Имейте в виду, однако, что long не будет заканчиваться нулем (обязательно, это может быть), поэтому вам нужно отслеживать, где его конец.

Например:

long list[MAX];
char *serial = list;
int chunk = sizeof(long);
int k;
for(k=0; k<(MAX*chunk); k++){
  // do something with the "char"
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...