C ++中的结构填充
如果我在C ++中有一个struct
,是否没有办法将它安全地读/写到跨平台/编译器兼容的文件中?
因为如果我理解正确,每个编译器都会根据目标平台进行不同的填充。
不,那是不可能的。 这是因为在二进制级缺乏C ++的标准化 。
Don Box写道(引自他的书Essential COM,COM作为更好的C ++一章)
C ++和可移植性
一旦决定将C ++类作为DLL进行发布,就会面临C ++的一个基本弱点 ,那就是缺少二进制级别的标准化 。 虽然ISO / ANSI C ++草案工作文件试图编译哪些程序将编译以及运行它们的语义效果是什么, 但它没有尝试标准化C ++的二进制运行时模型 。 第一次这个问题会变得明显的是,当客户端试图从C ++开发环境(而不是用于构建FastString DLL的环境)与FastString 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;
}
用gcc-4.3.4
编译它,你得到这个输出:
8
12
也就是说,即使两个结构都具有相同的成员,大小也是不同的!
代码在Ideone:http://ideone.com/HGGVl
底线是标准不会讨论如何完成填充,因此编译器可以自由作出任何决定,并且不能假定所有编译器都做出相同的决定。
如果你有机会自己设计结构,它应该是可能的。 基本思想是你应该设计它,这样就不需要在其中插入填充字节。 第二个诀窍是你必须处理差异性。
我将描述如何使用标量构造结构,但只要您对每个包含的结构应用相同的设计,就应该可以使用嵌套的结构。
首先,C和C ++的一个基本事实是,类型的对齐不能超过类型的大小。 如果会,那么使用malloc(N*sizeof(the_type))
分配内存是不可能的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
}
下一步是确定结构是否应以小或大端格式存储。 如果存储格式与主机系统的永久性不匹配,最好的方法是在写入之前或读取结构之后,在原处“交换”所有元素。
不,没有安全的方法。 除了填充之外,还必须处理不同的字节排序和不同大小的内置类型。
您需要定义一种文件格式,并将结构转换为该格式。 序列化库(例如boost :: serialization或google的协议缓冲区)可以帮助解决这个问题。
链接地址: http://www.djcxy.com/p/85861.html下一篇: How to correctly work on a GreaseMonkey userscript using git?