使用带有未命名嵌套数据类型的指定初始值设定项

我想知道是否有可能在未命名的结构数据成员中使用指定的初始化器…(Yikes,一口,但是,是的,这是我做的事情最干净的方式……)。 如果我有:

typedef struct MainStruct { union { uint8_t a8[16]; uint64_t a64[2]; }; uint64_t i64; } MainStruct_t; typedef struct OtherStruct { MainStruct_t main; int otherval; } OtherStruct_t; OtherStruct_t instance = { .main.a64 = { 0, 0 }, .otherval = 3 }; 

我尝试编译,我得到错误:

 tst3.c:16: error: unknown field 'a64' specified in initializer 

我也尝试过使用.main..a64 ,但我遇到了其他问题。 这是使用gcc 4.4。 不幸的是, MainStruct遍布整个代码,因此命名union将涉及更改数百个文件,所以我想避免这种情况。 如果可能的话,我还想避免在OtherStructMainStruct位置做任何假设。

您需要稍微更改语法, .main在初始化程序中初始化.main

 typedef struct MainStruct { union { uint8_t a8[16]; uint64_t a64[2]; }; uint64_t i64; } MainStruct_t; typedef struct OtherStruct { MainStruct_t main; int otherval; } OtherStruct_t; OtherStruct_t instance = { .main = {.a64 = { 0, 0 }}, .otherval = 3 }; 

这是一个有效的测试程序:

 #include  #include  typedef struct MainStruct { union { uint8_t a8[16]; uint64_t a64[2]; }; uint64_t i64; } MainStruct_t; typedef struct OtherStruct { MainStruct_t main; int otherval; } OtherStruct_t; OtherStruct_t instance = { .main = {.a64 = { 5, 10 }}, .otherval = 3 }; int main(void) { printf("%d, %d\n", (int) instance.main.a64[0], (int) instance.main.a64[1]); printf("%d\n", instance.otherval); } 

gcc -std=c11 -Wall -Wextra -Wpedantic ,这是程序输出:

 5, 10 3 

更新

虽然C99不支持未命名的结构或联合,但使用指定的初始化程序也应该至少使用C99。 这是一个例子:

 #include  struct Inner { int x; int arr[2]; }; struct Outer { char id[100]; struct Inner state; }; int main(void) { struct Outer instance = { .id = "first", .state = {.x = 5, .arr[0] = 1, .arr[1] = 2 }}; printf("instance id: %s\n", instance.id); printf("instance state.x = %d\n", instance.state.x); printf("instance state.arr[0] = %d\n", instance.state.arr[0]); printf("instance state.arr[1] = %d\n", instance.state.arr[1]); return 0; } 

gcc -std=c99 -Wall -Wextra -Wpedantic ,这是程序输出:

 instance id: first instance state.x = 5 instance state.arr[0] = 1 instance state.arr[1] = 2 

最后的说明

事实certificateOP的原始语法是:

 OtherStruct_t instance = { .main.a64 = { 0, 0 }, .otherval = 3 }; 

也应该同时适用于C99和C11,但在不允许初始化子对象的旧标准中不受支持。

C99不支持未命名的联合,但可以作为GNU扩展。 进一步的调查已经发现这个错误报告 ,它表明未命名结构和联合的指定初始化程序已在gcc 4.6中修复。 作为解决方法,有人建议在此链接中将违规初始化程序括在括号中; 还提到这个解决方法有点挑剔和位置依赖,这可以解释为什么它在这里不适用于OP。