如何使用嵌套在没有名称的结构中的c并集

How to use c union nested in struct with no name

本文关键字:结构 并集 有名称 何使用 嵌套      更新时间:2023-10-16

我正在进行所谓的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++中,并集是不可接受的。那么,一个人如何利用以这种方式宣布的工会,以及为了什么目的?

谢谢!

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

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

这意味着您可以访问其成员,就好像他们是RC_model_t_st的成员一样。

不确定也没有尝试过:

工会本身是不可进入的,但它的成员是可进入的。

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

为了详细说明Angew引用匿名并集和结构标准提供的答案,我想提供一个C源代码示例,该示例生成的输出显示了如何在由structunion组件组成的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;
}

此函数生成的输出看起来像:

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

输出显示了由于使用并集而导致的主structThings的各个组件之间的重叠。您还可以看到匿名structunion的组件与命名structunion的组件是如何被引用的。

同样为了好玩,我尝试在包含const UCHAR myArray[];的匿名union之后添加const UCHAR myArray[];的数组定义,看看会发生什么。编译器抱怨出现error C2020: 'myArray' : 'struct' member redefinition错误。上述Thingsstruct定义中对该添加进行了注释。然而,由于const UCHAR myArray[];的第二次使用是在命名的union中,所以编译是有效的,因为第二次的使用是通过指定并集的名称来访问的。

此处的代码(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
}
};

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

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

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

并集基本上用于节省内存&它的规模相当于工会中最大的成员

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