在C或C ++中制作非压缩非填充结构的最佳方法是什么?目标是:
typedef struct {
char first[3]; //padded to 8 because next type has size 8
double second;
char third;
} SomeStruct;
but do something to make sizeof(SomeStruct) be equal 17;
结构由外部库规范定义。我有两个决定:
1)
#pragma pack (push, 1)
typedef struct {
char first[3];
char unused[5]; // Manual padding of second field.
double second;
char third;
} SomeStruct;
#pragma pack (pop)
2)使用声明的第一个变体,但在序列化数据时写入(int)(&((SomeStruct*)0)->third) + sizeof(((SomeStruct*)0)->third)
而不是sizeof(SomeStruct)
。我不需要序列化这种结构的数组,所以可以这样做。
但他们都是肮脏的黑客。是否有一种标准方法可以去除C中的结构填充?
答案 0 :(得分:2)
C11现在有_Alignas
个关键字,可能会建议double
typedef struct {
char first[3]; //padded to 8 because next type has size 8
_Alignas(uint16_t) double second;
char third;
} SomeStruct;
如果可能的话,这会做更窄的对齐,即平台上double
的标准运算符能够应对这种对齐。 (如果不是你,无论如何你都被搞砸了。)
Clang已经实现了这个功能,而其他编译器(如gcc)已经有了接近它的扩展,因此您可以轻松地自己编写一个使用此语法的包装器,并且是“面向未来”。
编辑:我发帖后才看到你的问题也是关于C ++的。我认为C ++ 1具有与alignas
相同的功能。 (C11通过标准头文件中的宏具有alignas -> _Alignas
。)
答案 1 :(得分:1)
尝试按正确的顺序放置
#include <stdio.h>
struct s
{
char first[3];
char second;
double third;
};
int main()
{
printf("%u\n", sizeof(struct s));
return 0;
}
答案 2 :(得分:0)
如果外部库规范的大小为17个字节,那么SomeStruct的第零个声明是不准确的。正如James McNellis在评论中指出的那样,你的版本大小为24.但是,我们可以弄明白你的意思。
SomeStruct的第一个声明完成了你所需要的,因为在任何地方都没有填充,你输入5个未使用的字节以匹配外部库规范。您的结构有17个字节。所以这看起来像你的答案。
你的第二个提案不清楚,因为你没有说你的SomeStruct的第二个声明是什么。
如果使用SomeStruct数组,则无关紧要。正如James McNellis的评论指出的那样,该标准要求编译器允许数组的可能性,无论你是否使用某些数组。
(当然这假设double是8个字节,你的pragma以你想要的方式工作,等等。)