便携性问题

时间:2015-01-27 12:12:20

标签: c struct portability

我编写了一个程序,可以执行各种处理,并在文件中写入/读取结果。

这个“结果”在这样的结构中

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

让我说我用这些函数写/读

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

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

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

2 个答案:

答案 0 :(得分: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 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('\0', file);

可以直接保存浮点类型,它们通常在任何地方都有相同的大小:

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

答案 1 :(得分:3)

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

首先使用stdint.h

中的类型替换类型
#include <stdint.h>

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

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

 char values[256];

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