如何在C / C ++中填写struct padding?

时间:2015-02-23 15:50:27

标签: c++ c struct padding

假设我有以下结构:

typedef struct {
    int mID;
    struct in_addr mIP;
    size_t dataSize;
    // Another structure
    fairness_structure str;
    bool ack;
    bool stability;
    bool stop_message;
}HeaderType;

如您所知,结构的大小会因其对齐而有所不同。如何用一些数据填充字段之间的填充,比如用零?

2 个答案:

答案 0 :(得分:5)

只需使用memset初始化结构,填充也将被填充。

memset(&mystruct, 0, sizeof(HeaderType));

如果您只想填充打击垫,可以将指针转换为char*并进行算术处理。但在这种情况下,您必须知道编译器如何填充结构,或者使用#pragma pack自行强制执行。 您可以使用offsetof()宏来获取struct成员的偏移量。

char *off = (char *)&mystruct + offsetof(HeaderType, ack);
char *pad_start = off + sizeof(mystruct.ack);
char *pad_end   = (char *)&mystruct + offsetof(HeaderType, stability);

睡前阅读:The Lost Art of C Structure Packing

答案 1 :(得分:1)

控制填充位和字节的内容似乎不太有用。但是,如果您将结构的内容写入具有单个writefwrite调用的文件,您可能需要关注填充,并且可能希望确保它们具有一致的值,最好是0,倍。当您从文件中读回内容时,这并不重要,但为了使文件内容可预测和可重现。由于这个原因,已知某些开发工具会在对象或可执行文件中生成不可预测的内容,因此很难从源代码重建并检查签名。

因此,如果您真的需要这个,那么您需要一种简单易用的方法。

坏消息是C标准没有针对此的通用解决方案。

关于标准填充字节和位的内容的唯一保证是静态存储的未初始化结构。在这种情况下,Padding被保证为零(在托管环境中)。实际上,初始化结构也是如此,因为它对编译器编写者来说足够简单。

自动存储的本地结构怎么样?如果它们未初始化,则字段和填充内容都是不确定的。如果您只是用memset(&s, 0, sizeof(s))清除字节,则填充将被清除,您可以开始修改结构成员...再次出现坏消息:C标准描述为未指定的行为 在结构或联合中存储值时填充字节的值(6.2.6.1)。

换句话说,在结构成员中存储值可能会对填充位和字节的内容产生副作用。允许编译器生成执行此操作的代码,这样做可能更有效。

Marek描述的超出简单memset的方法非常麻烦,特别是如果你有位域。实际上,在手动初始化字段之前清除结构似乎是实现目的的最简单方法,而且我还没有看到编译器利用标准对填充字节的宽容。如果按值传递结构,则所有投注都会关闭,因为编译器可能会生成不复制填充的代码。

作为结论:如果您使用本地结构,请在使用前使用memset清除它们,并且不要按值传递它们。没有保证填充将保持0值,但这是你能做的最好。