C 使用具有未命名嵌套数据类型的指定初始值设定项
我想知道是否有可能在结构的未命名数据成员中使用指定的初始值设定项。。。(哎呀,一口,但是是的,这是做我想做的事情最干净的方式…)。如果我有:C 使用具有未命名嵌套数据类型的指定初始值设定项,c,gcc,initialization,designated-initializer,C,Gcc,Initialization,Designated Initializer,我想知道是否有可能在结构的未命名数据成员中使用指定的初始值设定项。。。(哎呀,一口,但是是的,这是做我想做的事情最干净的方式…)。如果我有: typedef struct MainStruct { union { uint8_t a8[16]; uint64_t a64[2]; }; uint64_t i64; } MainStruct_t; typedef struct OtherStruct { 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 };
当我试图编译时,我得到了一个错误:
tst3.c:16: error: unknown field ‘a64’ specified in initializer
我也尝试过使用
.main..a64
,但我遇到了其他问题。这与GCC4.4是一致的。不幸的是,MainStruct
在整个代码中都被使用,因此命名联合体需要更改数百个文件,因此我希望避免这种情况。如果可能的话,我还想避免对主结构
在其他结构
中的位置进行任何假设。您需要稍微更改语法,在实例
的初始值设定项中初始化.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 <stdio.h>
#include <stdint.h>
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);
}
更新
这种指定初始值设定项的使用至少也应适用于C99,尽管C99不支持未命名的结构或联合。以下是一个例子:
#include <stdio.h>
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;
}
最后说明
事实证明,OP的原始语法是:
OtherStruct_t instance = { .main.a64 = { 0, 0 }, .otherval = 3 };
还应适用于C99和C11,但在不允许初始化子对象的旧标准中不受支持
C99不支持未命名的联合,但可以作为GNU扩展提供。进一步的调查表明,gcc 4.6中固定了未命名结构和联合体的指定初始值设定项。作为解决方法,有人建议在此链接中将有问题的初始值设定项括在大括号中;还提到,此解决方法有点挑剔,并且依赖于位置,这可能解释了为什么它在这里不适用于OP.尝试查找未命名实体的名称?:-)如果你想把它们归零,那无论如何都可以。实际上,我还需要初始化为非零值,这取决于实例。。。我本希望gcc能够在这种情况下解析
main.a64
,但它似乎不起作用。这似乎使使用未命名联合的第二个成员进行初始化变得相当困难(使用第一个将非常简单,使用未指定的联合…刚刚尝试过…)谢谢--我已经尝试过了,但我得到了tst3.c:19:error:初始化器中指定的未知字段“a64”
。我正在使用它,它适用于新版本的gcc?它适用于我,并且应该根据标准工作。我用-Wpedantic
编译。我会马上发布一个工作测试。我假定您正在使用-std=c11
选项?gcc 4.4.7不支持-std=c1X
选项(刚刚选中,直到gcc 4.6才支持)。如果此解决方案在较新版本的gcc中有效,那么很高兴知道这一点。目前,我不得不为我的具体案例解决另一个(有点难看的)解决办法。我会将您的答案标记为已接受,因为似乎没有针对4.4的解决方案,并且它可能对其他希望继续这样做的人有用。我以前没有检查过(!),但您的原始语法也适用。即使在使用-std=c99
编译时收到警告,这两个版本都可以工作。也许这只是编译器的时代加上未命名的联合问题。。建议的解决方法是将未命名的联合初始值设定项括在大括号中,但错误报告中包含的注释表明这可能并不总是有效的。
instance id: first
instance state.x = 5
instance state.arr[0] = 1
instance state.arr[1] = 2
OtherStruct_t instance = { .main.a64 = { 0, 0 }, .otherval = 3 };