加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

联盟数据结构对齐

发布时间:2020-12-16 05:06:03 所属栏目:百科 来源:网络整理
导读:我正在使用一些(我认为是)具有联合的坏代码: union my_msg_union{ struct message5; char buffer[256]} message; 缓冲区中有来自通信的256个字节.结构类似于: struct message5 { uint8 id; uint16 size; uint32 data; uint8 num_ids; uint16 ids[4];} mess
我正在使用一些(我认为是)具有联合的坏代码:
union my_msg_union
{
  struct message5;
  char buffer[256]
} message;

缓冲区中有来自通信的256个字节.结构类似于:

struct message5 {
 uint8 id;
 uint16 size;
 uint32 data;
 uint8 num_ids;
 uint16 ids[4];
} message5d

在大量架构(8位AVR,16位菲利普斯,32位臂,32位x86和amd64)上编译相同的代码.

我认为的问题是使用了union:代码只是一串连续收到的字节进入缓冲区,然后通过结构读出值,而不考虑结构的对齐/填充.

果然,快速查看不同系统上的sizeof(message5d)给出了不同的结果.

然而令我感到惊讶的是,每当与char []的联合存在时,所有类型的所有结构的所有实例在所有系统上都会丢弃它们的填充/对齐,并确保是连续的字节.

这是C标准还是编译器作者为“帮助”提供的东西?

解决方法

此代码演示了与您描述的相反的行为:
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

struct message5
{
    uint8_t id;
    uint16_t size;
    uint32_t data;
    uint8_t num_ids;
    uint16_t ids[4];
};

#if !defined(NO_UNION)
union my_msg_union
{
    struct message5 msg;
    char buffer[256];
};
#endif /* NO_UNION */

struct data
{
    char const *name;
    size_t offset;
};

int main(void)
{
    struct data offsets[] =
    {
        { "message5.id",offsetof(struct message5,id) },{ "message5.size",size) },{ "message5.data",data) },{ "message5.num_ids",num_ids) },{ "message5.ids",ids) },#if !defined(NO_UNION)
        { "my_msg_union.msg.id",offsetof(union my_msg_union,msg.id) },{ "my_msg_union.msg.size",msg.size) },{ "my_msg_union.msg.data",msg.data) },{ "my_msg_union.msg.num_ids",msg.num_ids) },{ "my_msg_union.msg.ids",msg.ids) },#endif /* NO_UNION */
    };
    enum { NUM_OFFSETS = sizeof(offsets) / sizeof(offsets[0]) };

    for (size_t i = 0; i < NUM_OFFSETS; i++)
        printf("%-25s  %3zun",offsets[i].name,offsets[i].offset);
    return 0;
}

示例输出(Mac OS X 10.9 Mavericks上的GCC 4.8.2,64位编译):

message5.id                  0
message5.size                2
message5.data                4
message5.num_ids             8
message5.ids                10
my_msg_union.msg.id          0
my_msg_union.msg.size        2
my_msg_union.msg.data        4
my_msg_union.msg.num_ids     8
my_msg_union.msg.ids        10

联合中的偏移量与结构中的偏移量相同,如C标准所要求的那样.

你必须根据上面的代码给出一个完整的编译反例 – 并指定你正在编译的编译器和平台来获得你的偏差答案 – 如果你确实可以重现不正确的答案.

我注意到我必须将uint8等更改为uint8_t,但我认为这没有任何区别.如果是,您需要指定从uint8获取名称的标题.

更新的代码可以在有或没有union的情况下编译.使用-DNO_UNION编译时的输出:

message5.id                  0
message5.size                2
message5.data                4
message5.num_ids             8
message5.ids                10

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读