2013-04-15 3 views
3

рассмотрим следующую структуру:__attribute __ ((упакованный)) альтернативные

typedef struct __attribute__((packed)) a{ 
    int a1; 
    int b2; 
    char cArray[5]; 
    int c3; 
} Mystruct; 

Теперь в моем коде, Im делает это:

char source[50]; 
Mystruct mm; 
//... 
//initialization and other codes 
//... 
memcpy(&mm,source,sizeof(mm)); 

Я пытаюсь заполнить структуру из строки (из файла, чтобы быть более конкретным), и, следовательно, я не хочу заполнения. Но думаю, что упаковка влияет и на производительность.

Итак, мой вопрос в том, есть ли другой способ достичь того, чего я хочу?
Можно ли сделать то же самое (заполнение из строки) переменными-членами класса в C++? Если да, то как?

+0

Пожалуйста, разместите * фактический * код, а не его приближение. –

+0

Извините @PaulR, я не могу опубликовать фактический код прямо сейчас. однако приведенный выше код может объяснить мой вопрос. – Dipto

+3

Я настоятельно рекомендую вам приобрести и прочитать ['Write Portable Code'] (http://www.hookatooka.com/wpc/). Вы не хотите использовать этот подход. Не только потому, что он не переносится (думайте о проблемах с endianess), но он влияет на производительность и атомарность (32-разрядный доступ не согласован на x86 без префикса LOCK). Гораздо лучше [маршал/unmarshal] (http: //en.wikipedia.org/wiki/Marshalling_ (computer_science)), хотя это немного больше работы. – jszakmeister

ответ

5

Я настоятельно рекомендую вам приобрести и прочитать Write Portable Code. Вы не хотите использовать этот подход. Не только потому, что он не переносится (думайте о проблемах с endianess), но он влияет на производительность и атомарность (32-разрядный доступ не согласован на x86 без префикса LOCK). Это намного лучше, чем marshal/unmarshal‌, хотя это немного больше работы.

Идея маршалинга/демонтажа состоит в том, чтобы преобразовать ваши данные из одного формата в другой и обратно. Вот что такое фреймворки, как Google Protocol Buffers, ZeroMQ и многие другие, чтобы переносить данные в переносном режиме. У вас в основном есть специализированные функции, которые берут ваши «строковые» данные, о которых вы говорили, и вы анализируете их, проверяете, а затем назначаете его в свою структуру. Вы увидите, что маршалинг и сериализация используются взаимозаменяемо во многих контекстах.

Например, в вашем случае, вы можете иметь функцию с прототипом:

int 
unmarshal_mystruct(const char *data, MyStruct &m); 

Внутри вы бы разобрать данные из data и заполнить m. Это утомительно, поэтому многие используют рамки.

+0

не могли бы вы немного разобраться в маршалинге? – Dipto

3

Используйте код сериализации/десериализации. То есть например, чтение в байтовый массив, а затем преобразование значений в структуру. Это так много фреймворков (т. Е. 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); 
} 

Reading:

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); 
} 
+0

Спасибо @ Валери-Атаманюк, я понял концепцию. Одно дело, в 'read_int' не должно быть' * value = ntohl (tmp) '? – Dipto

+1

Я бы предложил не использовать магические числа. Почему бы не использовать 'sizeof (int)' и 'sizeof (d-> cArray)' вместо? –

+0

@ Dipto right, fixed –

 Смежные вопросы

  • Нет связанных вопросов^_^