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

Using designated initializers with unnamed nested data types

我想知道是否可以在结构的未命名数据成员中使用指定的初始值设定项...(哎呀,一口,但是是的,这是做我想做的事情的最干净的方法。 ..).如果我有:

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,因此命名联合会涉及更改数百个文件,所以我想避免这种情况。如果可能的话,我还想避免对 MainStructOtherStruct 中的位置做出任何假设。

您需要稍微更改一下语法,在 instance:

的初始化程序中初始化 .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);

}

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

5, 10
3

更新

尽管 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;
}

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

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

最后的笔记

原来OP的原语法为:

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

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

C99 不支持未命名联合,但可作为 GNU 扩展使用。进一步调查发现 this bug report,这表明未命名结构和联合的指定初始值设定项已在 gcc 4.6 中修复。作为解决方法,在 link 中建议将有问题的初始值设定项括在大括号中;还提到这个解决方法有点挑剔并且依赖于位置,这可以解释为什么它在这里对 OP 不起作用。