具有显式(手动)字段布局的C struct / union?

时间:2011-08-25 00:48:22

标签: c# c visual-c++

这个C#代码的C等价物是什么?

[StructLayout(LayoutKind.Explicit)]
struct Test
{
    [FieldOffset(0)] int a;  // Integer at byte offset 0
    [FieldOffset(1)] int b;  // Integer at byte offset 1
    [FieldOffset(3)] int c;  // Integer at byte offset 3
};

(我不在乎它是否是非可移植的,例如假设int是4个字节,等等。)

6 个答案:

答案 0 :(得分:2)

这似乎在Visual Studio下工作正常:

#pragma pack(push)

#pragma pack(1)
typedef union
{
    int a;
    struct
    {
        char unused0;
        int b;
    };
    struct
    {
        char unused1;
        char unused2;
        char unused3;
        int c;
    };
} Test;

#pragma pack(pop)

答案 1 :(得分:1)

这是一个可以在 clang、gcc 和 msvc 上工作的宏(尚未测试 msvc 版本):

#define YDUMMY(suffix, size) char dummy##suffix[size]
#define XDUMMY(suffix, size) YDUMMY(suffix, size)
#define DUMMY(size) XDUMMY(__COUNTER__, size)
#ifdef __GNUC__
#define EXPLICIT_UNION_START(name) union Test {
#define EXPLICIT_UNION_END() };
#define EXPLICIT_OFFSET_FIELD(foff, ftype, fname) struct __attribute__((packed)) { DUMMY(foff); ftype fname; };
#elif defined(_MSC_VER)
#define EXPLICIT_UNION_START(name) #pragma pack(push, 1) \
union Test {
#define EXPLICIT_UNION_END() }; \
#pragma pack(pop)
#define EXPLICIT_OFFSET_FIELD(foff, ftype, fname) struct { DUMMY(foff); ftype fname; };
#else
#error "What compiler is this?"
#endif

EXPLICIT_UNION_START(Test)
    EXPLICIT_OFFSET_FIELD(0, int, a)
    EXPLICIT_OFFSET_FIELD(1, int, b)
    EXPLICIT_OFFSET_FIELD(3, int, c)
EXPLICIT_UNION_END()

感谢未命名字段,访问定义字段的语法不会被虚拟名称污染:

int main() {
    union Test t;
    t.b = 13;
    printf("offset a = %zx\n", offsetof(union Test, a));
    printf("offset b = %zx\n", offsetof(union Test, b));
    printf("offset c = %zx\n", offsetof(union Test, c));
    printf("t.b = %d\n", t.b);
    return 0;
}

答案 2 :(得分:0)

这个怎么样。

union u_t {
    struct {
        int V;
    } a;
    struct {
        byte dummy;
        int V;
    } b;
    struct {
        byte dummy1;
        byte dummy2;
        byte dummy3;
        int V;
    } c;
};

虚拟字段用于强制偏移。我认为一些编译器可以强制字段或结构对齐,因此您需要在编译时确保该选项已关闭。请参阅pragma pack directive。获取a,b,c值的方法是引用并集中每个相应结构中的V字段。例如,如果你的类型是u_t,那么

  u.c.V = 17;

答案 3 :(得分:0)

您可以使用union,也许使用一些#defines来简化使用。

union Test {
    struct {
        int V_a;
    } s_a;
    struct {
        char V_a;
        int V_b;
    } S_b;
    struct {
        char V_a;
        short V_b;
        int V_c;
    } S_c;

#define a S_a.V_a
#define b S_b.V_b
#define c S_c.V_c
};

答案 4 :(得分:0)

不完全符合您的要求,但您应该可以使用bit fields获得类似的效果。

此外,对于Visual C ++,可能值得一看:__declspec(align(#))#pragma pack

答案 5 :(得分:0)

使用union的替代方法是使用方法来访问值,正如您可能应该做的那样。虽然它是C ++,你要求C - 但我假设C ++在你使用VC ++的基础上很好。

#ifdef __cplusplus
struct Test {
    int a() {
        return *(int*)&values_[0];
    }
    void a(int value) {
        *(int*)&values_[1] = value;
    }
    int b() {
        return *(int*)&values_[1];
    }
    void b(int value) {
        *(int*)&values_[1] = value;
    }
    int c() {
        return *(int*)&values_[3];
    }
    void c(int value) {
        *(int*)&values_[3] = value;
    }

private:
    char[8] values_;
};
#endif