如何使用嵌套在struct中的c union没有名称

zwx*_*zwx 14 c c++ anonymous unions

我正在研究所谓的Hotspot开源项目,看看实现我在struct中找到了一个令人讨厌的嵌套联合看起来像这样:

typedef struct RC_model_t_st
{
    union
    {
        struct block_model_t_st *block;
        struct grid_model_t_st *grid;
    };
    /* block model or grid model    */
    int type;
    thermal_config_t *config;
}RC_model_t;
Run Code Online (Sandbox Code Playgroud)

据我所知,在C/C++中,联合是不可接受的.那么有人如何利用以这种方式和目的宣布的工会呢?

谢谢!

Rei*_*ica 26

这是一个匿名联盟.在C++中,根据[class.union],第5段:

出于名称查找的目的,在匿名联合定义之后,匿名联合的成员被认为已在声明匿名联合的作用域中定义.

这意味着您可以像访问其成员一样访问其成员RC_model_t_st.

  • @zwx因为它仍然是一个联盟 - 它们占据相同的存储空间. (2认同)

Atm*_*ons 8

没有确定,没有尝试过:

工会本身是无法访问的,但它的成员是.

因此,你应该能够参考obj.blockobj.grid


Ric*_*ers 8

为了详细说明通过引用Angew有关匿名联合和结构的标准所提供的答案,我认为提供的C源代码与由该样品显示生成的输出值是如何内的分配的样品struct和一个union组成structunion组分。

Angew引用的标准是:

出于名称查找的目的,在匿名联合定义之后,匿名联合的成员被认为已在声明匿名联合的范围内定义。

struct由命名和匿名结构体和联合体组成的源代码如下所示。这是使用 Visual Studio 2005,#pragma (pack, 1)用于对齐char边界上的所有内容,以免出现内存漏洞。还定义了一个简单的 C 预处理器宏,以使输出更清晰且更易于编码。

typedef unsigned char UCHAR;

// use of Microsoft Visual Studio pragma to force char alignment for the struct.
#pragma pack(push, 1)
const struct {
    union {
        const UCHAR myArray[];  // this array shares memory with struct following
        struct {
            const UCHAR iOne;
            const UCHAR iTwo;
            const UCHAR iThree;
        };  // anonymous struct accessed by specifying Things.
    };      // anonymous union accessed by specifying Things.
//  const UCHAR myArray[];   // will cause error - "error C2020: 'myArray' : 'struct' member redefinition"
    union {
        const UCHAR myArray[];  // this array shares memory with struct following
        struct {
            const UCHAR iOne;
            const UCHAR iTwo;
            const UCHAR iThree;
        } s;    // named struct accessed by specifying Things.u.s
    } u;        // named union accessed by specifying Things.u
} Things = {1, 2, 4, 8, 9, 10, 22, 23, 24, 25};
#pragma pack(pop)

// a little helper macro to make the output easier to code.
#define PRINTF_VAL(x) printf ("%s %d \n", #x, x)

int itSelf (UCHAR iMask)
{
    int iMatch = -1;

    int jj = 0;
    jj = Things.myArray[0]; PRINTF_VAL(Things.myArray[0]);
    jj = Things.myArray[1]; PRINTF_VAL(Things.myArray[1]);
    jj = Things.myArray[2]; PRINTF_VAL(Things.myArray[2]);
    jj = Things.myArray[3]; PRINTF_VAL(Things.myArray[3]);
    jj = Things.myArray[4]; PRINTF_VAL(Things.myArray[4]);
    jj = Things.iOne; PRINTF_VAL(Things.iOne);
    jj = Things.iTwo; PRINTF_VAL(Things.iTwo);
    jj = Things.iThree; PRINTF_VAL(Things.iThree);

    jj = Things.u.myArray[0]; PRINTF_VAL(Things.u.myArray[0]);
    jj = Things.u.myArray[1]; PRINTF_VAL(Things.u.myArray[1]);
    jj = Things.u.myArray[2]; PRINTF_VAL(Things.u.myArray[2]);
    jj = Things.u.myArray[3]; PRINTF_VAL(Things.u.myArray[3]);
    jj = Things.u.myArray[4]; PRINTF_VAL(Things.u.myArray[4]);
    jj = Things.u.s.iOne; PRINTF_VAL(Things.u.s.iOne);
    jj = Things.u.s.iTwo; PRINTF_VAL(Things.u.s.iTwo);
    jj = Things.u.s.iThree; PRINTF_VAL(Things.u.s.iThree);

    return iMatch + 1;
}
Run Code Online (Sandbox Code Playgroud)

此函数生成的输出如下所示:

Things.myArray[0] 1
Things.myArray[1] 2
Things.myArray[2] 4
Things.myArray[3] 8
Things.myArray[4] 9
Things.iOne 1
Things.iTwo 2
Things.iThree 4
Things.u.myArray[0] 8
Things.u.myArray[1] 9
Things.u.myArray[2] 10
Things.u.myArray[3] 22
Things.u.myArray[4] 23
Things.u.s.iOne 8
Things.u.s.iTwo 9
Things.u.s.iThree 10
Run Code Online (Sandbox Code Playgroud)

输出显示在主的各种部件之间的重叠structThings因使用工会。您还可以看到匿名struct和的组件如何union被引用与命名struct和的组件相比union

也只是为了好玩,我尝试const UCHAR myArray[];在匿名union包含之后添加一个数组定义,const UCHAR myArray[];看看会发生什么。编译器抱怨错误error C2020: 'myArray' : 'struct' member redefinition。添加在上面的struct定义中被注释掉了Things。然而,由于第二次使用const UCHAR myArray[];是在一个命名union的编译工作,因为第二次使用是通过指定联合的名称来访问的。


小智 5

此处的代码 ( https://gist.github.com/klange/4042963 ) 显示了如何访问结构中的匿名联合。您只需访问嵌套联合的成员,就好像它们是结构的成员一样。

typedef struct {
    union {
        char * company;
        char * school;
        char * project;
    };
    union {
        char * location;
        char * url;
    };
    union {
        char * title;
        char * program;
    };

    time_t started;
    time_t left;

    char * description[];
} thing_t;

typedef thing_t job_t;

job_t yelp = {
    .company  = "Yelp, Inc.",
    .location = "San Francisco, CA",
    .title    = "Software Engineer, i18n",
    .started  = 1339977600,
    .left     = CURRENT,
    .description = {
        "Developed several internal tools and libraries",
        "Provided critical input and design work for Yelp's launch in Japan",
        NULL
    }
};
Run Code Online (Sandbox Code Playgroud)