рассмотрим следующую структуру:
typedef struct __attribute__((packed)) a{
int a1;
int b2;
char cArray[5];
int c3;
} Mystruct;
Теперь в моем коде я делаю это:
char source[50];
Mystruct mm;
//...
//initialization and other codes
//...
memcpy(&mm,source,sizeof(mm));
Я пытаюсь заполнить структуру из строки (из файла, чтобы быть более конкретным), и, следовательно, я не хочу дополнения. Но думаю, упаковка также влияет на производительность.
Итак, мой вопрос: есть ли другой способ достичь того, чего я хочу?
Можно ли сделать то же самое (заполнение из строки) переменными-членами класса в c ++? Если да, то как?
Я настоятельно рекомендую вам купить и прочитать Написать портативный код. Вы не хотите использовать этот подход. Не только потому, что он не переносимый (думаю, проблемы с бесконечностью), но он влияет на производительность и атомарность (32-разрядный доступ без выравнивания не является атомарным на x86 без префикса LOCK). Гораздо лучше маршал / распаковать, Хотя это немного больше работы заранее.
Идея маршалинга / демаршалинга заключается в преобразовании ваших данных из одного формата в другой и обратно. Это то, что нравится фреймворкам Google Protocol Buffers, ZeroMQ, и многие другие делают передачу данных портативным способом. В основном у вас есть специализированные функции, которые берут ваши «строковые» данные, о которых вы говорили, и вы анализируете их, утверждать это, а затем назначить его в вашей структуре. Вы увидите, что маршалинг и сериализация взаимозаменяемо используются во многих контекстах.
Например, в вашем случае у вас может быть функция с прототипом:
int
unmarshal_mystruct(const char *data, MyStruct &m);
Внутренне, вы бы проанализировали данные из data
и заселить m
, Это становится утомительным, поэтому так много людей используют фреймворки.
Используйте код сериализации / десериализации. То есть например, прочитать в байтовом массиве, а затем преобразовать значения в структуру. Это то, что делают многие фреймворки (т. Е. CORBA и т. Д.).
Недостатки: больше кода для записи.
Преимущества: лучшая мобильность, совместимость между платформами LE / BE. Например, ваш код может не работать на некоторых устройствах ARM.
Пример (структура):
typedef struct a
{
int a1;
int b2;
char cArray[5];
int c3;
} Mystruct;
Пишу:
void write_int(FILE *f, int value)
{
int32_t tmp = htonl(value); // write in BE form
fwrite(&tmp, 4, 1, f);
}
void a_write(Mystruct *d, FILE *f)
{
write_int(f, d->a1);
write_int(f, d->b2);
fwrite(d->cArray, 5, 1, f);
write_int(f, d->c3);
}
Чтение:
void read_int(FILE *f, int *value)
{
int32_t tmp;
fread(&tmp, 4, 1, f);
*value = ntohl(tmp);
}
void a_read(Mystruct *d, FILE *f)
{
read_int(f, &d->a1);
read_int(f, &d->b2);
fread(d->cArray, 5, 1, f);
read_int(f, &d->c3);
}