C++ 什么时候会出现结构打包问题?

C++ 什么时候会出现结构打包问题?,c++,struct,C++,Struct,我一直在阅读有关struct bit打包订单问题的文章,但由于接触面有限,我自己没有遇到过。然而,我注意到,这些讨论大多针对非常复杂的应用 我现在正在编写一个结构来保存来自ifstream的信息,就像这样 struct MyFileStruct { char data1[40]; int data2; char data3[12]; // etc.. }; ifstream fin; // .. snip .. fin.read((char*)&myfi

我一直在阅读有关struct bit打包订单问题的文章,但由于接触面有限,我自己没有遇到过。然而,我注意到,这些讨论大多针对非常复杂的应用

我现在正在编写一个结构来保存来自ifstream的信息,就像这样

struct MyFileStruct
{
    char data1[40];
    int data2;
    char data3[12];
    // etc..
};

ifstream fin;
// .. snip ..
fin.read((char*)&myfilestruct, sizeof(MyFileStruct));

我只是想,在这个简单的场景中,是否会出现任何问题,可能是在另一个操作系统或32/64位体系结构中。等等。那么,确切地说,什么时候可以考虑位打包顺序?

一般规则是,您可以读取使用同一编译器编译的代码编写的文件(包括编译器选项)。最简单的形式是一个程序,它写出二进制数据,以便以后可以读回。除此之外,您还需要了解特定于实现的行为,没有简单的答案。

一般规则是,您可以读取使用同一编译器编译的代码编写的文件(其中包括编译器选项)。最简单的形式是一个程序,它写出二进制数据,以便以后可以读回。除此之外,您还陷入了特定于实现的行为,没有简单的答案。

打包规则(以及类似的规则)可能成为一个考虑因素,包括您的示例,当

  • 程序是用不同的编译器编译的
  • 该程序使用同一编译器的不同版本编译(理论上)
  • 该程序使用不同的编译器选项进行编译,包括但不限于更改目标操作系统、目标硬件或32/64位设置
  • 编译器指令被添加到源代码中,例如
    #pragma pack
一条安全的一般规则是,只有读取结构的可执行文件是由同一可执行文件编写的,才能保证代码工作

当考虑到这一点时,打包问题(但不是endianness)的一个常见解决方案是使用非标准编译器指令以牺牲效率的方式删除打包

这可以通过Microsoft编译器和gcc来完成。

打包规则(以及类似的,打包规则)可以成为一个考虑因素,包括您的示例,当

  • 程序是用不同的编译器编译的
  • 该程序使用同一编译器的不同版本编译(理论上)
  • 该程序使用不同的编译器选项进行编译,包括但不限于更改目标操作系统、目标硬件或32/64位设置
  • 编译器指令被添加到源代码中,例如
    #pragma pack
一条安全的一般规则是,只有读取结构的可执行文件是由同一可执行文件编写的,才能保证代码工作

当考虑到这一点时,打包问题(但不是endianness)的一个常见解决方案是使用非标准编译器指令以牺牲效率的方式删除打包


这可以通过Microsoft编译器和gcc来完成。

对于该特定结构,您最可能遇到的问题是endian属性。在小尾端系统中,该
int
的最低寻址字节包含最低有效8位。在大端系统上,最高有效位为8位

因此,如果您将该结构的字节写入一种系统上的文件,将该文件传输到另一种系统,并将其读回,那么您将在
data2
中看到不同的值

但是,在使用其他结构或不寻常的系统/编译器时,您可能会遇到其他问题:

  • 基本类型的大小-
    int
    通常为4字节,但不要求如此
    long
    在不同的通用系统上具有不同的大小(Windows上为4字节,64位Linux上为8字节)。显然,如果您试图从文件读取结构,并期望从其他C++实现中实际写入的字节数不同,则存在问题。
  • 填充-允许编译器将未使用的字节放入成员之间的结构中。这通常是为了确保对齐。例如,在许多编译器中,
    int
    成员的偏移量始终是4的倍数。因为在结构中40是4的倍数,所以这不会有任何区别,但是如果第一个数组是39字节,那么对齐
    int
    的实现将插入一个未使用的字节,而不对齐的实现则不会。在某些CPU(例如x86)上,对齐
    int
    是有帮助的,但不是必需的,在这种情况下,编译器通常有办法对结构进行注释,以说明是否填充它

由于存在这些类型的差异,一般来说,将结构直接写入文件(或套接字)是不合法的。在特定的情况下,如果读它的人对该结构有完全相同的内存表示,这意味着如果你首先计算出字节的确切位置和含义,你就可以这样做,然后确保所有需要读/写文件的程序都可以使用该格式。

对于该特定结构,您最可能遇到的问题是端性。在小尾端系统中,该
int
的最低寻址字节包含最低有效8位。在大端系统上,最高有效位为8位

因此,如果您将该结构的字节写入一种系统上的文件,将该文件传输到另一种系统,并将其读回,那么您将在
data2
中看到不同的值

但是,在使用其他结构或不寻常的系统/编译器时,您可能会遇到其他问题:

  • 基本类型的大小-
    int
    通常为4字节,但不要求如此
    long
    在不同的通用系统上具有不同的大小(4 b