struct

时间:2015-11-02 06:00:30

标签: c arrays pointers memory struct

我对struct中字节的排序方式感到有些困惑。

我们说我有以下结构:

struct container {
    int myint;
    short myshort;
    long mylong;
};

现在,我想初始化类型为struct container的变量,就像下面一样,除了我希望使用数组执行它。

struct container container1 = {.myint = 0x12345678,
                               .myshort = 0xABCD,
                               .mylong = 0x12345678};

假设sizeof intlong4,而short的{​​{1}}为2

假设没有填充。

那么10 bytes的{​​{1}}的布局如何?

这取决于字节顺序吗?

会是这样的:

struct

或者喜欢:

0x12345678 ABCD 12345678

我想要做的是:我有以下的char数组:

0x78563412 CDAB 78563412

我想手动用数据填充此数组,然后char buffer[10] = {0}; memcpy

我应该做 [1]

struct

或应该是 [2]

buffer[0] = 0x12345678 & 0xFF;
buffer[1] = 0x12345678 >> 8 & 0xFF;
buffer[2] = 0x12345678 >> 16 & 0xFF;
buffer[3] = 0x12345678 >> 24 & 0xFF;
...
buffer[9] = 0x12345678 >> 24 & 0xFF;
在我做buffer[0] = 0x12345678 >> 24 & 0xFF; buffer[1] = 0x12345678 >> 16 & 0xFF; buffer[2] = 0x12345678 >> 8 & 0xFF; buffer[3] = 0x12345678 & 0xFF; ... buffer[9] = 0x12345678 & 0xFF; 之前

memcpy

而且,如果我正在写入数组并复制到memcpy(&container1, buffer, sizeof(container1); ,它是否可以跨系统移植,特别是在字节序方面?

修改 [1] 是否适用于小端机器和 [2] 的大端?

2 个答案:

答案 0 :(得分:2)

  

这取决于字节顺序吗?

是的,取决于机器的字节顺序。因此,您的逻辑将根据机器的字节顺序而改变。

由于结构填充,没有可移植方式* 来执行此操作。虽然不同的编译器确实提供了自定义方法来禁用struct padding。检查Force C++ struct to not be byte aligned

  • 您可以添加static_assert(需要C11支持),以确保您的代码不会编译,除非您的结构紧凑。您不会拥有可移植代码,但您仍然可以确定,如果您的代码编译,它将表现正常。

    static_assert(sizeof(container) == sizeof(int) + sizeof(short) + sizeof(long));
    

答案 1 :(得分:1)

还有一个问题,即结构中元素对齐的问题。

您的结构具有间隙以进行对齐。真实的布局就像你做的那样:

struct container {
    int myint;
    short myshort;
    char __pad__[2];  // padding to align mylong to 4/8 byte boundary
    long mylong;
};

使用union

怎么样?
union {
    struct container vals;
    char buf[10];
};

但是,为什么你想这样做?对于我能想到的几乎任何场景,可能有一种更清晰的方法来获得效果。

当你说 array 时,你的意思是你想要初始化你的结构数组吗?这可以做到:

struct container conts[3] = {
    { .myint = 1, .myshort = 2, .mylong = 3 },
    { .myint = 4, .myshort = 5, .mylong = 6 },
    { .myint = 7, .myshort = 8, .mylong = 9 }
};

BTW,在C中做static_assert的方法:

// compile time assertion -- if the assertion fails, we will get two case 0:'s
// which will cause the compiler to flag this
#define static_assert(_assert) \
    do { \
        switch (0) { \
        case (_assert): \
            break;
        case 0: \
            break; \
        } \
    } while (0)