便携性问题

Portability concern

我编写了一个程序,可以进行各种处理并将结果write/reads保存在一个文件中。

这个"result"在这样的结构中

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

假设我用这些函数写/读

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

我担心的是:如果结构是在 32b 机器上编写并在 64 机器上读取(或其他方式),会出现什么问题?

我不是要求对我目前正在做的事情进行任何改进,而是关于可移植性方面的工作方式问题。

根据我的经验,一切都会出错,因为平台上类型的大小不同。

首先将类型替换为 stdint.h

中的类型
#include <stdint.h>

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

你也不应该把字符串写成char*。当你再次阅读它时,你只会得到陈旧的指针。使用预定义大小的字符串:

 char values[256];

或者在单独的写入调用中手动写入字符串。

这里有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 0202 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('[=12=]', file);

~ 浮点数类型可以直接保存,一般大小都一样:

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