C/C++ union用法

在C/C++程序的编写中,当多个基本数据类型或复合数据结构要占用同一片内存时,我们要使用联合体;当多种类型,多个对象,多个事物只取其一时(我们姑且通俗地称其为“n 选1”),我们也

可以使用联合体来发挥其长处。首先看一段代码:

<pre name="code" class="cpp">union myun
{
	struct { int x; int y; int z; }u;
	int k;
}a;
int main()
{
	a.u.x =4;
	a.u.y =5;
	a.u.z =6;
	a.k = 0;
	printf("%d %d %d\n",a.u.x,a.u.y,a.u.z);
	return 0;
}

union类型是共享内存的,以size最大的成员大小作为自己的大小,这样的话,myun这个结构就包含u这个结构体,而大小也等于u这个结构体 的大小,在内存中的排列为声明的顺序x,y,z从低到高,然后赋值的时候,在内存中,就是x的位置放置4,y的位置放置5,z的位置放置6,现在对k赋 值,对k的赋值因为是union,要共享内存,所以从union的首地址开始放置,首地址开始的位置其实是x的位置,这样原来内存中x的位置就被k所赋的 值代替了,就变为0了,这个时候要进行打印,就直接看内存里就行了,x的位置也就是k的位置是0,而y,z的位置的值没有改变,所以应该是0,5,6

再看两个试题:

试题一:编写一段程序判断系统中的CPU 是Little endian 还是Big endian 模式?

分析:

作 为一个计算机相关专业的人,我们应该在计算机组成中都学习过什么叫Little endian 和Big endian。Little endian 和Big endian 是CPU 存放数据的两种不同顺序。对于整型、长整型等数据类型,Big endian 认为第一个字节是最高位字节(按照从低地址到高地址的顺序存放数据的高位字节到低位字节);而Little endian 则相反,它认为第一个字节是最低位字节(按照从低地址到高地址的顺序存放数据的低位字节到高位字节)。

例如,假设从内存地址0x0000 开始有以下数据:

0x12 0x34 0xab 0xcd

如 果我们去读取一个地址为0x0000 的四个字节变量,若字节序为big-endian,则读出结果为0x1234abcd;若字节序位little-endian,则读出结果为 0xcdab3412。如果我们将0x1234abcd 写入到以0x0000 开始的内存中,则Little endian 和Big endian 模式的存放结果如下:

地址               0x0000 0x0001 0x0002 0x0003

big-endian         0x12   0x34   0xab   0xcd

little-endian      0xcd   0xab 0x34   0x12

一般来说,x86 系列CPU 都是little-endian 的字节序,PowerPC 通常是Big endian,还有的CPU 能通过跳线来设置CPU 工作于Little endian 还是Big endian 模式。

解答:

显然,解答这个问题的方法只能是将一个字节(CHAR/BYTE 类型)的数据和一个整型数据存放于同样的内存

开始地址,通过读取整型数据,分析CHAR/BYTE 数据在整型数据的高位还是低位来判断CPU 工作于Little

endian 还是Big endian 模式。得出如下的答案:

typedef unsigned char BYTE;
int main(int argc, char* argv[])
{
	unsigned int num;
	BYTE *p = (BYTE*)#
	num = 0;
	*p = 0xff;
	if(num == 0xff)
	{
		printf("The endian of cpu is little\n");
	}
	else //num == 0xff000000
	{
		printf("The endian of cpu is big\n");
	}
	return 0;
}

除了上述方法(通过指针类型强制转换并对整型数据首字节赋值,判断该赋值赋给了高位还是低位)外,还有没

有更好的办法呢?我们知道,union 的成员本身就被存放在相同的内存空间(共享内存,正是union 发挥作用、做贡献的去处),因此,我们可以将一个CHAR/BYTE 数据和一个整型数据同时作为一个union 的成员,得出

如下答案:

int checkCPU()
{
	union w
	{
		int a;
		char b;
	} c;
	c.a = 1;
	return (c.b == 1);
}

实现同样的功能,我们来看看Linux 操作系统中相关的源代码是怎么做的:

static union { char c[4]; unsigned long mylong; } endian_test = {{ ‘l‘, ‘?‘, ‘?‘, ‘b‘ } };

#define ENDIANNESS ((char)endian_test.mylong)

Linux 的内核作者们仅仅用一个union 变量和一个简单的宏定义就实现了一大段代码同样的功能!由以上一段代码我们可以深刻领会到Linux 源代码的精妙之处!(如果ENDIANNESS=’l’表示系统为little endian,

为’b’表示big endian )

试题二:假设网络节点A 和网络节点B 中的通信协议涉及四类报文,报文格式为“报文类型字段+报文内容的结构体”,四个报文内容的结构体类型分别为STRUCTTYPE1~ STRUCTTYPE4,请编写程序以最简单的方式组

织一个统一的报文数据结构。

分析:

报文的格式为“报文类型+报文内容的结构体”,在真实的通信中,每次只能发四类报文中的一种,我们可以将四类报文的结构体组织为一个union(共享一段内存,但每次有效的只是一种),然后和报文类型字段统一组织成一个报文数据结构。

解答:

根据上述分析,我们很自然地得出如下答案:

<span style="font-size:18px;">typedef unsigned char BYTE;
//报文内容联合体
typedef union tagPacketContent
{
	STRUCTTYPE1 pkt1;
	STRUCTTYPE2 pkt2;
	STRUCTTYPE3 pkt1;
	STRUCTTYPE4 pkt2;
}PacketContent;
//统一的报文数据结构
typedef struct tagPacket
{
	BYTE pktType;
	PacketContent pktContent;
}Packet</span>;

时间: 2024-08-30 13:16:06

C/C++ union用法的相关文章

[C++]union用法

摘自cplusplus.com上关于union的解释: Unions allow one portion of memory to be accessed as different data types. Its declaration and use is similar to the one of structures, but its functionality is totally different:unions允许一部分内存可以访问不同的数据类型.他的声明和使用和结构体相同,但是他的

sql的union用法

sql中union是很常见的,尤其是创建视图时,完全离不开union. SQL UNION 操作符合并两个或多个 SELECT 语句的结果,UNION 内部的每个 SELECT 语句必须拥有相同数量的列.列也必须拥有相似的数据类型.同时,每个 SELECT 语句中的列的顺序必须相同. union包括union和union all两种语法,如下: SQL UNION 语法 SELECT column_name(s) FROM table1 UNION SELECT column_name(s) F

C语言中的union用法

union共用声明和共用一变量定义: "联合"是一种特殊的类,也是一种构造类型的数据结构.在一个"联合"内可以定义多种不同的数据类型, 一个被说明为该"联合"类型的变量中,允许装入该"联合"所定义的任何一种数据,这些数据共享同一段内存, 以达到节省空间的目的(还有一个节省空间的类型:位域). 这是一个非常特殊的地方,也是联合的特征. 另外,同struct一样,联合默认访问权限也是公有的,并且,也具有成员函数. 共用体(参考&q

oracle union 用法

[sql] view plaincopyprint?众所周知的几个结果集集合操作命令,今天详细地测试了一下,发现一些问题,记录备考. 假设我们有一个表Student,包括以下字段与数据: drop table student; create table student ( id int primary key, name nvarchar2(50) not null, score number not null ); insert into student values(1,'Aaron',78

SQL 基础:Select语句,各种join,union用法

一.基本的SELECT语句 1. “*”的注意事项:在SELECT语句中,用*来选取所有的列,这是一个应该抵制的习惯. 虽然节省了输入列名的时间,但是也意味着获得的数据比真正需要的数据多的多.相应的,也会降低应用程序的性能及网络性能. 良好的规则是只选所需. 2. join子句 join是用来定义如何从多个表中选取数据并组合成一个结果集. join必需是因为(1)我们所要获取的所有信息并不都在一个表中,或者(2)所要返回的信息都在一个表中,但是其上设置的条件信息却在另一个表中. join的共同点

Union用法及说明:

Union是用户合并多个select结果集的操作符,需要注意的是:select语句需要有相同的列数,类似的数据类型,且列的顺序相同,另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名.Union和Union All区别:默认Union会取出不同的值,如果你也想取出重复的值就用Union All, 原文地址:https://www.cnblogs.com/lxwphp/p/8328842.html

MySQL UNION 与 UNION ALL 语法与用法

1.MySQL UNION 语法 MySQL UNION 用于把来自多个 SELECT 语句的结果组合到一个结果集合中.语法为: SELECT column,... FROM table1 UNION [ALL] SELECT column,... FROM table2 ... 在多个 SELECT 语句中,对应的列应该具有相同的字段属性,且第一个 SELECT 语句中被使用的字段名称也被用于结果的字段名称. 1.1.UNION 与 UNION ALL 的区别 当使用 UNION 时,MySQ

Oracle 中union的用法

UNION 指令的目的是将两个 SQL 语句的结果合并起来,可以查看你要的查询结果. 例如: SELECT Date FROM Store_Information UNION SELECT Date FROM Internet_Sales 注意:union用法中,两个select语句的字段类型匹配,而且字段个数要相同,如上面的例子,在实际的软件开发过程,会遇到更复杂的情况,具体请看下面的例子 select  '1' as type,FL_ID,FL_CODE,FL_CNAME,FLDA.FL_P

SQL中MINUS的用法

minus指令是运用在两个 SQL 语句上.它先找出第一个 SQL 语句所产生的结果,然后看这些结果有没有在第二个 SQL 语句的结果中.如果有的话,那这一笔资料就被去除,而不会在最后的结果中出现.如果第二个 SQL 语句所产生的结果并没有存在于第一个 SQL 语句所产生的结果内,那这笔资料就被抛弃. MINUS 的语法如下: [SQL 语句 1] MINUS [SQL 语句 2] 我们继续使用一样的例子: Store_Information 表格 store_name  Sales  Date