2015-01-27 4 views
2

Я написал программу, которая выполняет все виды обработки и записи/чтения результатов в файле.Опасность переносимости

Это «результат» находится в структуры, как этот

struct res 
{ 
    char id; 
    char* values; 
    int count; 
    long samplenumber; 
}; 

и давайте говорить, что я писать/читать с функциями, как эти

write(file, &result, sizeof(struct res)); 
read(file, &result, filesize(file)); 

Мое беспокойство: что может пойти не так, если структуры написано на 32-битной машине и читается на 64 (и наоборот)?

Я не прошу о каких-либо улучшениях того, что я сейчас делаю, а о проблемах с тем, как все работает с точки зрения переносимости.

+0

Oh Извините, я использую C. – Neva

+0

Определите все с размером: например, 'unsigned char',' uint32_t' (или 'int32_t') и рассмотрите возможность изменения' long', потому что это изменяется; вы можете захотеть 'uint64_t' – Gophyr

ответ

4

Есть 4 проблемы здесь:

~ Размеры типов могут быть разными. (Используйте типы из stdint.h как uint32_t.)

~ Компилятор обычно будет вставлять отступы в вашу структуру, как

struct res 
{ 
    char id; 
    /* unused byte */ 
    /* unused byte */ 
    /* unused byte */ 
    char* values; 
    int count; 
    long samplenumber; 
}; 

~ порядок байты целых чисел могут быть разными. Например, 3555896322 может быть представлен как
D3 F2 AC 02 или 02 AC F2 D3.

~char* будет сохранен в файл как бесполезный указатель. Вам нужно написать строку самостоятельно, байт по байт.

Решение:

~ Используйте типы из stdint.h.

~ Не используйте структуры для сохранения. (Или используйте так называемый #pragma pack, но имейте в виду, что он не переносится.)

~ Запись числа байт за байтом, как

uint32_t var = 3555896322; 
putc(var >> 0 & 0xff, file); 
putc(var >> 8 & 0xff, file); 
putc(var >> 16 & 0xff, file); 
putc(var >> 24 & 0xff, file); 

~ писать строки байт за байтом, например:

const char *ptr = "Hello, young programmer!"; 
while (*ptr) 
    putc(*(ptr++), file); 
putc('\0', file); 

~ Типы с плавающей точкой может быть они обычно имеют одинаковый размер:

float a = 1.23; 
fwrite(&a, sizeof (float), 1, file); 
+0

> Не используйте structs для сохранения. Следует упомянуть, что есть функция, называемая «упаковка», которая позволяет избежать этого. '#pragma pack' в VC или' __attribute __ ((упакован)) 'делает вещь. – myaut

+0

@ user300234 Конечно, они могут, но AFAIK это очень редкий случай. – HolyBlackCat

3

Из моего опыта, все пойдет не так, потому что размеры типов различны на платформах.

Прежде всего заменить типы с единицами из stdint.h

#include <stdint.h> 

struct res 
{ 
    uint8_t id; 
    char*  values; 
    uint32_t count; 
    uint32_t samplenumber; 
}; 

Вы также не должны писать строку как char*. Когда вы прочтете это снова, вы просто получите устаревший указатель. Использовать строку предопределенного размера:

char values[256]; 

Или напишите строку вручную в отдельном вызове на запись.

+6

Это все еще не обязательно переносимо, потому что размер прокладки между членами может измениться. И некоторые платформы имеют различное двоичное представление (big endian vs little endian и т. Д.). – interjay

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

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