对同一数据使用两种不同的结构

时间:2012-04-03 19:07:09

标签: c++ struct marshalling

我需要将UUID从C ++代码转移到将在基于Intel 8051的加密狗上运行的C代码。我已经定义了以下结构来以最便携的方式表示UUID:

struct UUID {
    unsigned char data1[4];
    unsigned char data2[2];
    unsigned char data3[2];
    unsigned char data4[8];
};

嗯,这个字节数组的结构在C ++中使用起来不太方便,所以我定义了一个中间帮助类,如下所示:

#include <stdint.h> // #include <cstdint> in C++0x

class UUIDAssign {
public:
    uint32_t data1;
    uint16_t data2;
    uint16_t data3;
    uint64_t data4;

    operator UUID() const
    {
        UUID uuid(*((UUID*)this));
        return uuid;
    }    
};

这样我就可以写出类似的内容:

UUIDAssign assign1 = {0x80DFDD28, 0xF033, 0xB027, 0xCDD2078FC78A};
UUID uuid1 = assign1;

我没有看到另一种方便地用一些值初始化UUID结构的方法。好吧,从字符串表示中初始化它是恕我直言,这是一个值得怀疑的选择。

问题是:

  1. 我通过中间帮助器类实现UUID初始化的方式是不正确的?你能给我一些建议吗?
  2. 填充怎么样?它会影响从UUIDAssign传输到UUID的数据吗?

2 个答案:

答案 0 :(得分:1)

原则上你可能会遇到填充/对齐问题,但考虑到你使用它们的顺序类型,这是不太可能的。您更有可能在不同平台上遇到不同字节序的问题。

除此之外,您编写的代码违反了C ++的严格别名规则。虽然UUID类型只包含char数组,但 不是char数组。因此,您无法完全排除优化程序出现问题的可能性(以静默错误的代码形式)。

如果您不需要将UUID类作为POD,那么最简单的解决方案就是UUID的构造函数,如下所示:

struct UUID {
    unsigned char data1[4];
    unsigned char data2[2];
    unsigned char data3[2];
    unsigned char data4[8];
    UUID(uint32_t d1, uint16_t d2, uint16_t d3, uint64_t d4)
    {
      data1[0] = d4 & 0xff;
      data1[1] = (d4 >> 8) & 0xff;
      data1[2] = (d4 >> 16) & 0xff;
      data1[3] = d4 >> 24;
      // etc.
    }
};

然后您可以将UUID对象定义为

UUID uuid(0x80DFDD28, 0xF033, 0xB027, 0xCDD2078FC78A);

如果你的UUID对象需要是POD,你可以这样做:

struct UUID {
    unsigned char data1[4];
    unsigned char data2[2];
    unsigned char data3[2];
    unsigned char data4[8];
};

struct UUIDAssign: UUID
{
    UUIDAssign(uint32_t d1, uint16_t d2, uint16_t d3, uint64_t d4)
    {
      data1[0] = d4 & 0xff;
      data1[1] = (d4 >> 8) & 0xff;
      data1[2] = (d4 >> 16) & 0xff;
      data1[3] = d4 >> 24;
      // etc.
    }
};

并像这样初始化:

UUID uuid = UUIDAssign(0x80DFDD28, 0xF033, 0xB027, 0xCDD2078FC78A);

答案 1 :(得分:1)

Union是你的朋友:

#ifdef __CPLUSPLUS
    #include <cstdint>
    #include <cstdio>
#else
    #include <stdint.h>
    #include <stdio.h>
#endif

union UUID {
    struct {
        uint32_t data1;
        uint16_t data2;
        uint16_t data3;
        uint64_t data4;
    } cpp;
    struct {
        unsigned char data1[4];
        unsigned char data2[2];
        unsigned char data3[2];
        unsigned char data4[8];
    } c;
};

int main() {
    UUID uuid = {0x80DFDD28, 0xF033, 0xB027, 0xCDD2078FC78A};

    printf("%u\n%x%x%x%x\n", uuid.cpp.data1, uuid.c.data1[3], uuid.c.data1[2], uuid.c.data1[1], uuid.c.data1[0]);

    return 0;
}
输出

(在little-endian上,注意第二个值的反向打印):

2162154792
80dfdd28

您必须访问“c”子结构的顺序为machine-dependent