2

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

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是,整个代码都使用了 ,因此命名联合将涉及更改数百个文件,所以我想避免这种情况。如果可能的话,我还想避免对 inside 的位置进行任何MainStruct假设OtherStruct

4

1 回答 1

4

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

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 扩展使用。进一步的调查发现了这个错误报告,它表明未命名结构和联合的指定初始化程序在 gcc 4.6 中已修复。作为解决方法,建议在此链接中将有问题的初始化程序括在大括号中;还提到这种解决方法有点挑剔并且取决于位置,这可以解释为什么它不适用于 OP。

于 2017-03-29T20:51:50.480 回答