4

在 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 中的结构填充的标准方法?

4

3 回答 3

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. (C11alignas -> _Alignas通过标准头文件中的宏。)

于 2012-08-30T08:40:14.553 回答
0

尝试以正确的顺序放置它

#include <stdio.h>

struct s
{
    char first[3];
    char second;
    double third;
};

int main()
{
    printf("%u\n", sizeof(struct s));
    return 0;
}
于 2012-08-30T06:54:53.267 回答
0

如果外部库规范规定大小为 17 字节,那么您对 ​​SomeStruct 的第零个声明是不准确的。正如 James McNellis 在评论中指出的那样,您的版本大小为 24。但是,我们可以弄清楚您的意思。

您对 SomeStruct 的第一个声明完成了您所需要的,因为任何地方都没有填充,并且您放入了 5 个未使用的字节以匹配外部库规范。您的结构有 17 个字节。所以这看起来像你的答案。

您的第二个提案不清楚,因为您没有说明 SomeStruct 的第二个声明是什么。

是否使用 SomeStruct 数组并不重要。正如 James McNellis 的评论所指出的那样,标准要求编译器允许数组的可能性,无论您是否使用一些。

(当然,这假设 double 是 8 个字节,并且您的 pragma 以您想要的方式工作,等等。)

于 2012-08-30T07:00:34.157 回答