使用char数组成员填充联合

时间:2014-07-21 23:41:43

标签: c arrays unions

我有一个C联合体,有许多字段,很可能在不同的平台上有不同的大小:

union foo {
    int a;
    wchar_t b;
    bar *c;
    baz d;
}

现在我想为这个联合添加一个char数组,这个数组与我可以实现的一样大,没有它会导致整个联合变大。

之类的东西
union foo {
    ...
    char z[sizeof(union foo)];
}

当然,除了不会编译,因为此时union foo的大小还不知道。

是否有一种技巧可以让我“填充”#34;与char数组的联合?

2 个答案:

答案 0 :(得分:2)

嗯,有:

union bar {
    union foo {
        int a;
        wchar_t b;
        bar *c;
        baz d;
    } f;
    char z[sizeof(union foo)];
};

得到正确的大小,但是在访问其他成员时你必须坚持f.

AFAIK如果没有f,就无法做到这一点。但是,正如user1969104所暗示的那样,对您的问题可能有更好的解决方案。

这是一个丑陋的黑客:

#define UNION_FOO_Z(u) ( *(unsigned char (*)[sizeof(union foo)])&u )

用法:

union foo f;
printf("%zu\n", sizeof UNION_FOO_Z(f));

这种黑客可能存在对齐问题(虽然不太可能)。

答案 1 :(得分:1)

首先,使用除数组之外的所有内容声明一个联合,

union foo_almost {
    int a;
    wchar_t b;
    bar *c;
    baz d;
};

然后用一切声明联盟,

union foo {
    int a;
    wchar_t b;
    bar *c;
    baz d;
    char z[sizeof(union foo_almost)];
};

有些人使用宏来执行此操作 - 将第一部分声明为FOO_ALMOST,但他们真正保存的只是输入,

#def FOO_ALMOST \
    int a; \
    wchar_t b; \
    bar *c; \
    baz d;
union foo_almost {
    FOO_ALMOST
};

然后,

union foo {
    FOO_ALMOST
    char z[sizeof(union foo_almost)];
};

现在,sizeof(union foo_almost)和sizeof(union foo)应该是相同的。但是,您的编译器仍然可以分配比union foo类型的对象更多的内存。

不需要丑陋的黑客,除非你认为附加类型的联盟foo_almost是丑陋的。

注意,

union foo_almost fa;
union foo f;
printf("%zu\n", sizeof(fa));
printf("%zu\n", sizeof(f));