【问题标题】:Define a packed version of a C struct定义 C 结构的打包版本
【发布时间】:2014-08-29 06:39:06
【问题描述】:

我在代码之外的某个地方定义了一个 C 结构。我可以定义相同结构的打包版本吗?如果我从一开始就定义自己的结构,那很容易:

struct test {
    // members
} __attribute__((packed));

我定义了一个简单的结构并尝试了两种可能性,这个:

struct test {
    int x;
    double y;
    char z;
};

struct test_p {
    struct test __attribute__((packed)) s;
};

还有这个:

struct test {
    int x;
    double y;
    char z;
};

struct test_p {
    struct test p;
} __attribute__((packed));

但是,这些都不起作用(尽管都编译得很好)在我的系统上打印 sizeof(struct test_p)=24(我在 64 位机器上使用 gcc 4.8.2),这与 sizeof(struct test) 相同.有没有办法达到预期的效果?

以防万一您想知道:我想解析通过网络接收的数据包,这些数据包只是打包结构。问题是,我不能修改头文件,因为它是第三方库的一部分,而且结构本身包含的字段太多,无法一一复制。我当然可以将结构定义复制到我自己的标题中并制作打包版本——实际上这是我现在使用的解决方案——但我只是想知道是否有更简洁的解决方案不涉及复制整个定义.

【问题讨论】:

  • 一个有趣的问题,但我不认为你会找到一个优雅的解决方案; “您只能在枚举、结构或联合的定义上指定此属性,而不是在未定义枚举类型、结构或联合的 typedef 上。” gcc.gnu.org/onlinedocs/gcc/Type-Attributes.html

标签: c gcc struct


【解决方案1】:

gcc 引入了__attribute__((packed)) 正是为了避免您正在寻求的危险影响:结构的定义应该在所有使用相同定义的用户应用程序和库之间二进制兼容。

但是 gcc 也提供了一种方法来打包 the old fashioned, dangerous way - #pragma pack(push,n)#pragma pack(pop)。只有当第 3 方头文件仅包含结构定义,或者您不使用头文件中的任何其他内容时,它才会可靠地工作。像这样使用它们:

#pragma pack(push,1)
#include "theheader.h"
#pragma pack(pop)

否则,我个人会简单地复制粘贴结构定义,重命名它,然后在我自己的标题中添加__attribute__((packed))。用编译指示包装整个标题真的是一个肮脏的黑客。并且第 3 方标头可能会以意想不到的方式发生变化,从而导致 the bit rot

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多