C++ C+中的结构填充+; /COD>,难道没有办法安全地读/写它到跨平台/编译器兼容的文件吗?< /P>

C++ C+中的结构填充+; /COD>,难道没有办法安全地读/写它到跨平台/编译器兼容的文件吗?< /P>,c++,struct,C++,Struct,因为如果我理解正确的话,每个编译器根据目标平台的不同而“填充”不同。不,没有安全的方法。除了填充,还必须处理不同的字节顺序和不同大小的内置类型 您需要定义文件格式,并将结构转换为该格式。序列化库(例如boost::Serialization或google的protocolbuffers)可以帮助实现这一点。长话短说,没有。没有独立于平台、符合标准的方法来处理填充 填充在标准中称为“对齐”,并在3.9/5中开始讨论: 对象类型具有对齐方式 要求(3.9.1、3.9.2)。这个 完整对象类型的对齐方

因为如果我理解正确的话,每个编译器根据目标平台的不同而“填充”不同。

不,没有安全的方法。除了填充,还必须处理不同的字节顺序和不同大小的内置类型


您需要定义文件格式,并将结构转换为该格式。序列化库(例如boost::Serialization或google的protocolbuffers)可以帮助实现这一点。

长话短说,没有。没有独立于平台、符合标准的方法来处理填充

填充在标准中称为“对齐”,并在3.9/5中开始讨论:

对象类型具有对齐方式 要求(3.9.1、3.9.2)。这个 完整对象类型的对齐方式是 实现定义的整数 表示字节数的值; 对象被分配到一个地址 这符合对齐要求 它的对象类型

但它从那个里继续下去,并蜿蜒到标准的许多黑暗角落。对齐是“实现定义的”,这意味着在不同的编译器之间,甚至在同一编译器下的地址模型(即32位/64位)之间,对齐可以是不同的


除非您有真正苛刻的性能要求,否则您可能会考虑将数据以不同的格式存储到磁盘上,例如char字符串。当自然格式可能是其他格式时,许多高性能协议使用字符串发送所有内容。例如,我最近处理的一个低延迟exchange提要将日期发送为如下格式的字符串:“20110321”,发送时间类似:“141055.200”。尽管此exchange提要全天每秒发送500万封邮件,但它们仍然使用字符串来处理所有事情,因为这样可以避免结尾不连贯和其他问题。

如果您有机会自己设计结构,这应该是可能的。基本思想是,您应该设计它,这样就不需要在其中插入pad字节。第二个诀窍是,必须处理endianess中的差异

我将描述如何使用标量构造结构,但是您应该能够使用嵌套结构,只要您对每个包含的结构应用相同的设计

<>首先,C和C++中的一个基本事实是,类型的对齐不能超过类型的大小。如果会,那么就不可能使用
malloc(N*sizeof(the_type))
分配内存

布局结构,从最大的类型开始

 struct
 {
   uint64_t alpha;
   uint32_t beta;
   uint32_t gamma;
   uint8_t  delta;
接下来,手动填充结构,以便最终匹配最大的类型:

   uint8_t  pad8[3];    // Match uint32_t
   uint32_t pad32;      // Even number of uint32_t
 }

下一步是决定该结构是以小端还是大端格式存储。如果存储格式与主机系统的endianess不匹配,最好的方法是在写入结构之前或读取结构之后就地“交换”所有元素。

否。这是不可能的。这是因为C++在二进制级别.< 写(引用他的书,chapter COM作为更好的C++)

C++与可移植性
一旦决定 将C++类作为DLL 面临着一个基本的问题 C++的弱点,即缺乏 二进制级别的标准化。 虽然ISO/ANSI C++草案 工作文件试图编纂 程序将编译,并且 运行它们的语义效果将 是,它没有试图标准化 C++的二进制运行时模型。这个 这个问题第一次会变成 很明显,当客户端尝试链接时 针对FastString DLL的导入库从 一个C++开发环境 而不是用来建造 快速字符串DLL

结构填充由不同的编译器执行。即使使用同一个编译器,结构的打包对齐方式也可能因使用的内容而异

不仅如此,如果您编写的两个结构的成员完全相同,唯一的区别在于它们的声明顺序不同,那么每个结构的大小可以(而且通常)不同

比如说看这个,

struct A
{
   char c;
   char d;
   int i;
};

struct B
{
   char c;
   int i;
   char d;
};

int main() {
        cout << sizeof(A) << endl;
        cout << sizeof(B) << endl;
}
也就是说,即使两个结构具有相同的成员,大小也是不同的


底线是,标准没有讨论应该如何进行填充,因此编译器可以自由做出任何决定,不能假设所有编译器都做出相同的决定。

“结构(或类)的大小可能不等于其成员大小之和。”@Thomas:没错。这只是乐趣的开始。通过执行二进制I/O所获得的效率(性能)通常不能证明花在研究、设计、开发,特别是调试和维护上的钱是合理的。源代码应该简单易懂,但并不简单。这听起来很有趣。但是你能得到更详细的信息吗:为什么你要按类型长度降序排列,为什么你要填充偶数的uint32\u t?@Phil,一个基本类型,比如
uint32\u t
,可以(潜在地)有一个匹配其大小的对齐要求,在这种情况下是四个字节。编译器可以插入填充来实现这一点。通过手动执行此操作,编译器无需执行此操作,因为对齐方式总是正确的。缺点是,在对对齐要求不太严格的系统上,手动填充的结构将比编译器填充的结构大。您可以按升序或降序执行此操作,但如果按升序排列int,则需要在结构的中间插入更多的焊盘……只有在计划在数组中使用结构时,才需要在结构的末尾填充。@jwg。在一般情况下(例如,当您使用struct时)
8
12