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

时间:2012-11-29 11:27:55

标签: c++ c unions anonymous

我正在研究所谓的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;

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

谢谢!

6 个答案:

答案 0 :(得分:25)

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

  

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

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

答案 1 :(得分:8)

没有确定,没有尝试过:

工会本身不可访问,但它的成员是。

因此,您应该可以参考obj.blockobj.grid

答案 2 :(得分:4)

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

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

答案 3 :(得分:2)

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

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

答案 4 :(得分:2)

为了详细说明Angew引用有关匿名联合和结构的标准提供的答案,我想提供一个C源代码示例,该示例生成的输出显示如何在structunion内分配值由structunion组成的struct

Angew引用的标准是:

  

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

由命名和匿名结构和联合组成的#pragma (pack, 1)的源代码如下所示。这是使用Visual Studio 2005,char用于对齐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; } 边界上的所有内容,以便没有内存空洞。还定义了一个简单的C预处理器宏,使输出更清晰,更容易编码。

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

输出显示由使用联合引起的主Thingsstruct的各个组件之间的重叠。您还可以查看匿名unionstruct的组件与指定的unionconst UCHAR myArray[];的组件的对比情况。

另外,为了好玩,我尝试在包含union的匿名const UCHAR myArray[];之后添加error C2020: 'myArray' : 'struct' member redefinition的数组定义,以了解会发生什么。编译器抱怨错误为struct。上述Things的{​​{1}}定义中添加了添加内容。但是,由于const UCHAR myArray[];的第二次使用位于命名union中,因此编译有效,因为通过指定联合的名称来访问第二次使用。

答案 5 :(得分:-3)

首先,我想说一个联合,是一个不同类型的变量的集合,就像一个结构。但是,对于工会,您一次只能在一个字段中存储信息。

工会基本上用于节省内存和它的大小等于联盟中最大的成员。

要访问联合的数据字段,请使用点运算符(。),就像对结构一样,并由@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