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

问题描述 投票:0回答:6

我正在开发所谓的 Hotspot 开源项目,在查看实现时我发现结构中有一个令人讨厌的嵌套联合,如下所示:

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;

据我所知,在 C/C++ 中,联合是无法访问的。那么,有人如何利用以这种方式声明的 union 以及出于什么目的呢?

谢谢!

c++ c struct unions anonymous
6个回答
40
投票

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

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

这意味着您可以访问其成员,就像他们是

RC_model_t_st
的成员一样。


11
投票

不确定也没有尝试过:

工会本身不可访问,但其成员可以。

因此您应该能够参考

obj.block
obj.grid


10
投票

为了详细说明 Angew 引用有关匿名联合和结构的标准提供的答案,我想提供一个 C 源代码示例,其中包含该示例生成的输出,显示如何在

struct
union
内分配值由
struct
union
组件组成。

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

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

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

输出显示了由于使用联合而导致的主要

struct
Things
的各个组件之间的重叠。您还可以查看匿名
struct
union
的组件与命名
struct
union
的组件的引用方式。

也只是为了好玩,我尝试在包含

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


8
投票

这里的代码(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
    }
};

4
投票

在匿名联合中声明的名称可以直接使用,就像非成员变量一样。 这样做的一个很好的理由是节省内存。

#include <iostream>

int main(int argc, char **argv) {
   union {
      double first;
      double second;
   };

   first = 10.001;
   second = 3.141592;
   std::cout << first << " " << second << std::endl;

   first = 10.002;
   std::cout << first << " " << second << std::endl;
}

-2
投票

首先我想说的是 联合,是不同类型变量的集合,就像结构一样。但是,使用联合,您在任何时候只能将信息存储在一个字段中。

联合主要用于节省内存&它的大小等于联合的最大成员。

要访问联合的数据字段,请使用点运算符(.),就像访问结构一样,并由@Atmocreations 进行解释。当一个值被分配给一个成员时,其他成员会被淘汰,因为它们共享相同的内存。

工会可能有用的一个例子是

union time    
        {
        long time_in_sec;
        double time_in_mili_sec;
        }mytime;

.... 上面的联合可用于存储当前时间(以秒为单位)或将时间精确到秒。或者它可以用来将时间精确到毫秒。据推测,有时您会想要其中之一,但不会两者兼而有之。这个声明看起来应该很熟悉。它与结构体定义相同,但使用关键字 union 而不是 struct。

了解更多信息http://msdn.microsoft.com/en-us/library/5dxy4b7b(v=vs.80).aspx

© www.soinside.com 2019 - 2024. All rights reserved.