回答
不,这是不可能的。这是因为缺少C++在二进制级别的标准化。
C++和可移植性
一旦决定要 由分发C++类的(从他的书Essential COM,章COM作为一种更好的C++报价) DLL,其中一个 面临着的一个基本问题 C++的弱点,也就是lac k的 标准化在二进制级别。 虽然ISO/ANSI C++草案 工作文件试图编纂这 程序编译和什么运行它们将 是,的 语义效果也没有试图规范 的C++二进制运行时模型。该 第一次这个问题将成为 明显的是,当一个客户端尝试对FastString DLL的导入库从 一个C++的研究与开发环境等 比一个用于构建 FastString DLL链接 。
结构填充由不同的编译器完成。即使您使用相同的编译器,根据您使用的pragma pack,结构的打包对齐方式也可能不同。
不仅如此,如果你写两个结构,其成员是正是一样的,唯一的不同的是,在他们声明的顺序是不同的,那么每个结构的大小可以(而且经常是)不同。
例如,看到这种情况,
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
的底线是,标准不谈论填充应该怎么做,所以编译器可以自由地做出任何决定,你不能承担所有的编译器做同样的决定。
有'__attribute __((packed ))'我用于共享内存结构以及用于映射网络数据的结构。它确实会影响性能(请参阅http://digitalvampire.org/blog/index.php/2006/07/31/why-you-shouldnt-use-__attribute__packed/),但它对网络相关结构非常有用。 (就我所知,这不是一个标准,所以答案依然如此)。 – Pijusn 2015-06-08 07:11:55
我不明白为什么struct A的大小是8而不是更多。 { char c; // 那这个呢? char d; // size 1 + padding of 3 int i; // size 4 }; – Dchris 2017-03-03 08:01:28
@Dchris - 编译器可能很小心地确保每个字段基于自己的自然对齐进行对齐。 c和d是一个字节,因此无论您将它们放在单字节CPU指令的哪个位置,它们都是对齐的。然而,int需要在一个4字节的边界上对齐,要达到那个边界需要在d之后填充两个字节。这让你到8。 – hoodaticus 2017-05-25 20:58:22
您可以使用类似boost::serialization
之类的东西。
不,没有安全的方法。除了填充之外,还必须处理不同的字节排序和不同大小的内置类型。
您需要定义一种文件格式,并将结构转换为该格式。序列化库(例如boost :: serialization或google的协议缓冲区)可以帮助解决这个问题。
“结构(或类)的大小可能不等于其成员大小的总和。” – 2011-03-22 22:21:04
@Thomas:没错。这只是开始的乐趣。 – Erik 2011-03-22 22:23:05
长话短说,没有。没有平台无关的标准符合方式来处理填充。
填充被称为在标准 “对准”,并且它开始在3.9/5讨论它:
对象类型具有对准 要求(3.9.1,3.9.2)。完整对象类型的对齐方式为 实现定义的整数 表示多个字节的值; 对象分配在地址 ,满足其对象类型的对齐要求 。
但它从那里继续前进,并转移到标准的许多黑暗角落。对齐是“实现定义的”,这意味着它可以在不同编译器之间不同,甚至在编译器的相同下的地址模型(即32位/ 64位)上不同。
除非您有严格的性能要求,否则您可能会考虑以不同的格式(如字符串)将数据存储到光盘。当自然格式可能是其他内容时,许多高性能协议都会使用字符串发送所有内容。例如,我最近处理的低延迟交换馈送发送日期为格式如下的字符串:“20110321”,时间类似地发送:“141055.200”。尽管此交换馈送整天发送500万条消息,但它们仍然使用字符串处理所有内容,因为这样可以避免排序和其他问题。
如果你有机会自己设计结构,它应该是可能的。基本思想是你应该设计它,这样就不需要在其中插入填充字节。第二个诀窍是你必须处理差异性。
我将介绍如何使用标量构造结构,但只要您对每个包含的结构应用相同的设计,就应该可以使用嵌套的结构。
首先,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
}
下一步是决定是否结构应存放在小或大endian格式。如果存储格式与主机系统的字节不匹配,最好的方法是在写入之前或读取结构之后,在原地10“交换”所有元素。
这听起来很有趣。但是,您能详细了解一下:为什么按照长度递减的顺序排列它,为什么要填充它,使得偶数个uint32_t? – Phil 2015-02-21 22:52:15
@Phil,一个基本类型,比如'uint32_t',可以(可能)有一个匹配它的大小的对齐需求,在这个例子中是4个字节。编译器可以插入填充来实现这一点。通过手动执行此操作,编译器无需执行此操作,因为对齐总是正确的。缺点是在对齐要求不太严格的系统上,手动填充的结构将比编译器填充的结构大。您可以按照升序或降序完成此操作,但是如果您按升序执行int,则需要在结构体的中间插入更多垫... – Lindydancer 2015-02-22 08:34:45
...仅在您需要时才需要填充结构体的结尾计划在数组中使用它。 – Lindydancer 2015-02-22 08:35:13
- 1. C结构填充问题
- 2. 填充C++ POD结构
- 3. C结构中的对齐/填充
- 4. 结构填充
- 5. 填充结构
- 6. 在结构c中填充数组#
- 7. 将C++结构填充为2的幂
- 8. 结构填充解释
- 9. 填充结构更有效
- 10. 使用memcpy填充结构
- 11. 使用snprintf填充结构
- 12. 如何填充树结构?
- 13. 如何填充结构/类
- 14. 数据结构填充
- 15. 用String []填充结构体?
- 16. C++使用memcpy填充结构中的矢量
- 17. 在结构中填充字符指针
- 18. 为什么要在C++结构中添加填充符?
- 19. 填充结构的阵列动态
- 20. 想要填充元数据的结构
- 21. 填充和包装的结构
- 22. 填充在彩车的结构
- 23. 从c中的ini文件填充两个独立的结构c
- 24. 填充结构C的分段错误,缩小到一行
- 25. 填充具有多个值的C#结构阵列一次
- 26. C - 使用静态数据填充结构的方法
- 27. 不使用结构数组填充tableview
- 28. 填充和打印结构阵列
- 29. 零长度数组结构填充
- 30. 结构填充如何工作?
通过执行二进制I/O获得的效率(性能)往往不足以证明研究,设计,开发,特别是调试和维护所花费的资金。源代码应该很容易理解,但并不简单。 – 2011-03-22 22:24:50