【问题标题】:How can I span bit field across a union?如何跨联合跨越位字段?
【发布时间】:2016-05-05 08:48:09
【问题描述】:

这是我想要的结构:

typedef struct someip_header { 
    union { 
        uint32_t message_id;
        struct {
            uint16_t service_id; 
            uint8_t for_rpc : 1; 
            union {
                uint16_t method_id : 15;
                uint16_t event_id : 15;
            };
        };
    };
} someip_header_t;

(原因是如果for_rpc为1,则后15位表示事件ID,否则表示方法ID)

但是这个结构的大小是 5 个字节(打包),我猜是因为编译器不会让 union 不对齐。如果我只用uint16_t val : 15 替换内部联合,则大小会按预期恢复到 4 个字节:

typedef struct someip_header { 
    union { 
        uint32_t message_id;
        struct {
            uint16_t service_id; 
            uint8_t for_rpc : 1; 
            uint16_t method_event_id : 15;
        };
    };
} someip_header_t;

只是想知道,有没有办法打包这个?这真的只是化妆品,但仍然......

【问题讨论】:

  • 虽然不是我最喜欢的东西,但 MISRA 在禁止使用联合和位字段时是正确的。更改的编译器开关或新的编译器/目标平台/工具链等可能会破坏此代码。例如,for_rpc 的对齐方式可能会因工具链而异。与其像这样编写标头,不如使用序列化函数来完成它可能是一个更好的主意。有关更多信息,请参阅stackoverflow.com/questions/1044654/bitfield-manipulation-in-c。进一步的想法:从 ASN.1 生成代码。
  • 在第一个示例中,内部结构的大小至少为 5 个字节。如果定义的成员占用 5 个字节,那么它们占用的字节数不能少于 5 个。
  • @2501 总位数等于 4 个字节(偶数)。
  • @PawelVeselov Union 不是位域,因此 for_rpc 的剩余位不能用于联合内的位域。

标签: c


【解决方案1】:

在字节级别形成union

typedef struct someip_header { 
    union { 
        uint32_t message_id;
        struct {
            uint16_t service_id; 
            union {
                struct {
                    uint8_t for_rpc : 1; 
                    uint16_t method_id : 15;
                };
                struct {
                    uint8_t for_rpc_2 : 1; 
                    uint16_t event_id : 15;
                };
            };
        };
    };
} someip_header_t;

【讨论】:

  • 可以删除 for_rpc_2 并将其全部省略,使其更加简洁,恕我直言。
  • 对不起,我的意思是从字面上删除 for_rpc_2,作为一个名称,创建一个匿名的 1 位孔。
  • @PawelVeselov:很公平。我不会声称自己对 C 有很好的掌握,只是足以让我到达我需要去的地方。
猜你喜欢
  • 2011-09-23
  • 1970-01-01
  • 1970-01-01
  • 2021-09-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-04
  • 1970-01-01
  • 2017-04-23
相关资源
最近更新 更多