使用具有未命名嵌套数据类型的指定初始化程序 [英] Using designated initializers with unnamed nested data types

查看:170
本文介绍了使用具有未命名嵌套数据类型的指定初始化程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道是否可以在结构的未命名数据成员中使用指定的初始值设定项...(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:初始化程序中指定的未知字段'a64'

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

解决方案

您需要稍微更改语法,在初始化程序中为<$初始化 .main
$ b $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b 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\\\
,instance.otherval);

$ b

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

  5,10 
3



更新



指定的初始值设定项也应该至少与C99一起工作,尽管C99不支持未命名的结构或联合。这里是一个例子:

  #include  

struct Inner {
int x;
int arr [2];
};

struct Outer {
char id [100];
struct内部状态;
};

int main(void)
{
struct Outer instance = {.id =first,
.state = {.x = 5,.arr [ 0] = 1,.arr [1] = 2}};

printf(instance id:%s\\\
,instance.id);
printf(instance state.x =%d \ n,instance.state.x);
printf(instance state.arr [0] =%d \\\
,instance.state.arr [0]);
printf(instance state.arr [1] =%d \\\
,instance.state.arr [1]);

返回0;
}

编译gcc -std = c99 -Wall -

 实例ID:第一个
实例state.x = 5
instance state.arr [0] = 1
instance state.arr [1] = 2



Final Note



事实证明,OP的原始语法为:

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

也可以在C99和C11上工作,但在不允许初始化的旧标准中不受支持的子对象。



在C99中不支持未命名的联合,但可用作GNU扩展。进一步的调查发现这个错误报告,它暗示了指定的初始值设定项未命名的结构和联合会在gcc 4.6中修复。作为解决方法,在此链接中建议将有问题的初始化程序放在括号中;还有人提到这个解决方法是有点挑剔和位置相关的,这也许可以解释为什么它在这里不适用于OP。


I'm wondering if it is possible to use designated initializers in unnamed data members of structs... (Yikes, a mouthful, but yes, it is the cleanest way to do what I'm trying to do...). If I have:

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

and I try to compile, I get the error:

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

I've also tried using .main..a64, but I'm getting other issues. This is with gcc 4.4. Unfortunately, the MainStruct is used all over the code, so naming the union would involve changing hundreds of files, so I'd like to avoid that. I'd also like to avoid any assumptions about position of MainStruct within OtherStruct if possible.

解决方案

You need to change the syntax a bit, initializing .main within the initializer for 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 };

Here is a working test program:

#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);

}

Compiled with gcc -std=c11 -Wall -Wextra -Wpedantic, here is the program output:

5, 10
3

Update

This use of designated initializers should also work with at least C99, though C99 does not support unnamed structures or unions. Here is an example:

#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;
}

Compiled with gcc -std=c99 -Wall -Wextra -Wpedantic, here is the program output:

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

Final Note

It turns out that OP's original syntax of:

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

should also work on both C99 and C11, but is not supported in older standards which do not allow initialization of subobjects.

Unnamed unions are not supported in C99, but are available as a GNU extension. Further investigation has turned up this bug report which suggests that designated initializers for unnamed structs and unions were fixed in gcc 4.6. As workaround, it was suggested at this link to enclose the offending initializer in braces; it is also mentioned that this workaround is a bit finicky and position dependent, which may explain why it does not work here for OP.

这篇关于使用具有未命名嵌套数据类型的指定初始化程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆