在一个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 }
};
但是要避免,因为这是一种大肆宣传自动化的常规模式。
答案 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)
};