在编译时在const结构类型之间转换

时间:2015-02-11 07:43:01

标签: c struct unions compile-time

在一个API中给定一个常量结构,在其他API中将其解释为16个连续的uint8_t字节,C中是否有一个方法可以在编译时进行此转换:

我想要实现的是

 const union {
     struct a {
         uint32_t a;
         uint16_t b;
         uint16_t c;
         uint8_t d[8];
     } a;
     uint8_t b[16];
 } foo = { .a = { 0x12341243, 0x9898, 0x4554,
                { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 } } };

struct from_other_api manifest = {
    .appuuid = foo.b;
    // { foo.b[0], foo.b[1], ...  }
};

这种方法以及评论行中的第二个版本不幸地给出了错误错误:初始化元素不是常量,即使这肯定看起来像一样

业务原因是定义struct from_other_api manifest和常量内存blob都是一个API,不需要修改。转换可以手动完成

struct from_other_api manifest = {
    .appuuid = { 0x43, 0x12, 0x34, 0x12, 0x98, 0x98, 0x54, 0x45,
                 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }
};

但是要避免,因为这是一种大肆宣传自动化的常规模式。

3 个答案:

答案 0 :(得分:2)

此声明未声明变量。

struct a {
     uint32_t a;
     uint16_t b;
     uint16_t c;
     uint8_t d[8];
 };

要在a内声明一个名为union且结构相同的变量,请使用:

const union {
    struct {
         uint32_t a;
         uint16_t b;
         uint16_t c;
         uint8_t d[8];
     } a; // now a is accessible with a.a, a.b, a.c and a.d[i].
     uint8_t b[16];
} foo = { .a = { 0x12341243, 0x9898, 0x4554,
            { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 } } };

答案 1 :(得分:1)

您不能在数组初始值设定项中传递除文字之外的任何内容。 请改用memcpy(3)

struct from_other_api manifest = {
    // initialize other members
};
memcpy(manifest.appuuid, foo.b, sizeof (manifest.appuuid));

答案 2 :(得分:1)

在C中,常量变量不能用于常量表达式。

如果您可以在运行时初始化manifest,则可以使用Snaipes答案中的memcpy来执行此操作。

但是如果必须在编译时初始化manifest,则可能需要(ab)使用预处理器。它不会太漂亮,但它有效:

#define ID 0x12341243, 0x9898, 0x4554, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08

#define FOO(nnn)  { .a = FOO2(nnn) }
#define FOO2(a, b, c, d, e, f, g, h, i, j, k) \
    { a, b, c, { d, e, f, g, h, i, j, k } }

#define MAN(nnn) MAN2(nnn)
#define MAN2(a, b, c, d, e, f, g, h, i, j, k) \
    { a >> 0 & 0xFF, a >> 8 & 0xFF, a >> 16 & 0xFF, a >> 24 & 0xFF, \
    b >> 0 & 0xFF, b >> 8 & 0xFF, \
    c >> 0 & 0xFF, c >> 8 & 0xFF, \
    d, e, f, g, h, i, j, k }

const union {
    ...
 } foo = FOO(ID);

struct from_other_api manifest = {
    .appuuid =  MAN(ID)
};