《C语言参悟之旅》新鲜试读连载9

9.2  共用体

C语言除了提供结构体这种可包含多种类型数据的构造类型外,还提供了一种从形式上看和结构体堪称“孪生兄弟”的构造类型——共用体(union)。

本节从共用体的概念入手,从共用体的概念、与结构体的异同、使用等方面进行详细的介绍。

9.2.1   什么是共用体

现实生活中,某些事物往往可以用多种方式去表述,各种方式的地位是平等的,都是从不同的侧面去反应这个事物。例如,古人用的字、名、号,都是对一个人的称谓,但是会根据不同的场合和情况使用其中的一种。又例如,用数字和用优、良、中、差都可以表示成绩,具体使用上可能根据成绩的种类不同而选用其中的一种方式。

如果这些方式可以用同一种类型来表示,那么数组“勉强”能够用来对其进行存储,但浪费存储空间。而如果其数据类型不同,数组就“无能为力”了。结构体似乎也能对其进行表述,但并不是最佳的方式。针对这种情况下,C语言提供的共用体数据类型。

共用体,亦称联合,是有别于前述任何一种数据类型的特殊数据类型,其用来描述类型不相同的数据。与结构体不同的是:共用体对成员存储时采用覆盖技术,共享(部分)存储空间,成员被分配在同一段内存空间中。成员既可以具有相同的数据类型,也可以具有不同的数据类型。  

共用体定义与结构体相似,其一般形式为:

union 共用体名

{

数据类型 成员名1

数据类型 成员名2

……

数据类型 成员名n

};

例如,下面定义一个表示成绩的共用体:

union mark

{

int score;      //表示分数

char degree[4]; //表示等级

};

其如图9.15所示:

9.15 共用体mark

9.2.2   共用体与结构体

共用体和结构体,作为两种构造类型,从形式上看极其相似,但确实是两种不同的数据类型,可以说是“貌似神离”。下面从外部形式(外部)和内存使用(内部)两方面对其进行比较。

1. 外部的“情投意合”

共用体的定义、共用体变量的定义、共用体变量的引用等方面和结构体形式相同,可以简单的看作用union关键字替代struct关键字。具体说明如下:

l         类似与结构体变量的三种定义方式,共用体变量也有三种形式的定义方式。即先定义共用体类型,在定义共用体变量;定义共用体类型的同时定义共用体变量;不含共用体类型名定义共用体变量。

例如,下面用第二种方式定义共用体变量liming

union mark

{

int score;      //表示分数

char degree[4]; //表示等级

} liming;

l         与结构体变量类似,可以使用“.”运算符引用其成员,但不能直接引用共用体变量。

比如,下面对变量的引用是合法的:

liming.score=90;                //给共用体变量成员赋值

printf(“%s/n”,liming.degree);   //输出共用体变量成员值

而下面的引用是非法的:

printf(“%d,%s”, liming);        //不能引用共用体变量

l         与结构体同样的是,编译器只为共用体变量分配内存空间,和不为共用体名分配内存空间。

2. 内部的“各怀鬼胎”

共用体和结构体之所以是两种不同的类型,是因为在内存中的表示形式不同。可以简单的认为,共用体变量所占的内存长度等于其成员变量中所占存储空间最大的那个。而结构体变量其所占的内存长度等于其成员变量所占内存之和。

例如,下面定义一个结构体变量sum

struct

{

int i;

float f;

} sum //定义一个结构体变量

和一个共用体变量max

union

{

int i;

float f;

} max //定义一个共用体变量

两个变量在内存中的表示可能如图9.16所示:

9.16 结构体和共用体的内存表示

9.16中,每个框代表1个字节,假设int型数据占用2个字节的内存,float型数据占用4个字节的内存。结构体变量sum所占的内存大小等于其成员if所占内存大小之和,即6字节;而共用体变量max所占内存大小等于其成员中占内存最大的成员f所占内存大小,即4字节。

注意:在许多操作系统中,结构体的大小可能大于其内部成员大小之和,这是因为系统对数据存储进行了“内存对齐”,从而导致了存储上的间隙。所谓内存对齐是系统对数据类型的一种限制,其要求某种类型对象的地址必须是某个值n(通常是248)的倍数,从而来简化处理器和存储器之间接口的硬件设计。

其中,Linux的对齐策略是2字节数据类型,例如,short的地址必须是2的倍数。而较大的数据类型如:intint*floatdouble则必须是4的倍数。而Windows的策略要求更为严格,其要求任何k字节对象的地址必须是k的倍数。比如要求一个double类型对象的地址必须是8的倍数。所以开发时如果要用到结构体类型的大小,则需要查阅使用的操作系统、编译器的相关资料做相应的处理。

 

 

最新作品《C语言参悟之旅》全新上市,敬请关注!
官方网站:
http://www.tqbooks.net/product/gb/product_detail.asp?catalogid=10&productid=1474
China-pub有售:
http://www.china-pub.com/49980

如果你想同我交流,欢迎点击链接http://student.csdn.net/space.php?uid=113770和我成为好友
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值