C 可移植性问题

C 可移植性问题,c,struct,portability,C,Struct,Portability,我已经编写了一个程序,可以进行各种处理,并在文件中写入/读取结果 这个“结果”在这样的结构中 struct res { char id; char* values; int count; long samplenumber; }; 假设我用这样的函数写/读 write( file, &result, sizeof(struct res) ); read(file, &result, filesize(file) ); 我担心的是:如果

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

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

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;
};

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

这里有4个问题:

~类型的大小可以不同。(使用
stdint.h
中的类型,如
uint32\u t

~编译器通常会在结构中插入填充,如

struct res
{
    char  id;
    /* unused byte */
    /* unused byte */
    /* unused byte */
    char* values;
    int   count; 
    long  samplenumber;
};
~整数的Endianness可以不同。例如,
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);

哦,对不起,我用C来定义所有的大小:即,<代码>无符号char <代码>,<代码> UTI32 32 t < /代码>(或<代码> iT32×t < /代码>),并考虑更改<代码>长< /C> >,因为这是不同的;您可能希望
uint64\t
这仍然不一定是可移植的,因为成员之间的填充大小可能会改变。有些平台有不同的二进制表示法(大端和小端等)>不使用结构保存。您应该提到的是,有一种叫做“打包”的功能可以避免这种情况<在VC中使用code>#pragma pack或
uuuu属性((packed))
可以做到这一点。@user300234他们当然可以,但恐怕这是非常罕见的情况。
float a = 1.23;
fwrite(&a, sizeof (float), 1, file);