联合union十数据的引用类型转换十一位域或位字段.ppt_第1页
联合union十数据的引用类型转换十一位域或位字段.ppt_第2页
联合union十数据的引用类型转换十一位域或位字段.ppt_第3页
联合union十数据的引用类型转换十一位域或位字段.ppt_第4页
联合union十数据的引用类型转换十一位域或位字段.ppt_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1,九、联合union 十、数据的引用类型转换 十一、位域或位字段,第12章 结 构 与 联 合,2,九、联合union 1. 联合的特性和定义 由关键字struct声明的数据描述称为结构类型而union 或class声明的数据描述称为联合类型或类类型,分别简称为 结构和联合或类。 结构、联合、类是集合数据类型。 int、float等是系统预先取好的可以直接使用的类名, 关键字struct和union 或class后紧跟的标识符则是用户引入 的类名,需要事先加以声明。,3,在程序设计中常出现非此即彼的数据,这些数据的类型 可以不同,需要将其放置在同一片内存。 关键字union 建立的数据类型为用户引入的联合类型, 简称联合。联合一方面是节省内存空间,另一方面是特殊的 编程考虑。 联合的特性和定义: 联合类型定义的变量称为联合变量。指向联合变量的指 针简称为联合指针。联合类型的声明和联合变量的定义采用 与结构类似的语法,不同的是联合使用关键字union。,4,将前面关于结构声明复制过来略加变动并用union替代 struct得到: union UnionName 联合 联合名 type member; 数据类型 成员名 ; type2 member2; 数据类型2 成员名2; typen membern; 数据类型n 成员名n; ; ; 关键字union用于声明同一片内存可以存放不同类型的 数据,但在一个时刻只有某一类型的数据处于有效的状态。,5,联合类型声明中的数据成员具有如下的性质: a. 不同的成员占有起始地址相同的内存区域,这些成 员以并排的方式重合在一起。 b. 该内存区域的长度确定为所有成员中占有内存空间 最长的成员所对应的长度。 c. 在一个具体的时刻仅包含一种数据成员有效虽然成 员可以是集合型的数据。 d. 初始化联合变量时默认对第一个成员进行赋值亦仅 对一个成员赋值,初始值的类型属性应与第一个成员的类型 属性一致,否则编译器至少给出警告。 e. C+中联合不参入继承机制即联合类既不作基类也不 作派生类,不能有虚拟函数。,6,例 联合的内存和结构的内存大小比较 #include typedef struct s_a double d; char c9; A; typedef struct s_b double d; long k2; B; typedef union u_t A a; B b; U; typedef struct s_t A a; B b; S; void main (void) printf (“sizeof(A)= %d,“, sizeof (A); printf (“sizeof(B)= %d,“,sizeof (B); printf (“sizeof(U)= %d,“, sizeof (U); printf (“sizeof(S)= %d“, sizeof (S); /输出:sizeof (A)= 24,sizeof (B)= 16,16, sizeof (U)= 24,24,sizeof (S)= 40,7,联合一经声明就可以定义联合变量、联合数组和联合指 针。 箭头运算符“-”与圆点运算符“.”可以用来访问联合中 的成员,箭头运算符“-“的左侧是联合指针,圆点操作符“.“ 的左侧是联合变量,右侧是联合中的成员。 这和结构变量的使用规则一致。 不同的是结构变量拥有结构中各独立的成员所占内存之 和; 联合变量则仅是最大成员所拥有的内存,这一片内存可 由若干类型属性不同的成员适当索引,它们齐头地占有同一 块内存。,8,联合遵循先声明后定义再使用的次序。如下所示: typedef union u_t int k4; long member; float y; U; U obj, *pobj; obj.member /联合变量名.成员名 pobj-member /联合指针名-成员名 三个步骤可以合为一体,再加上初始化格式为: union u_t int k4; long member; float y; b = 1,2,3,4; 初始化只对第一个联合成员进行。该凝练的格式声明一 个名为u_t的联合名,其拥有三个并置的成员,第一个是int 型的数组成员k4、第二个是long型的成员member,第三 个是float型的成员y.这三个成员的内存起始地址是一样的。,9,例 联合指针入口形参和联合引用返回 #include inline int f(int k) return k; typedef union u_t char* s; int (*f)(int); int d; Un ; Unn+),10, Un y= initial ( /输出:abcd,abcd 1,2 3,3 联合变量、联合指针和联合引用可以作为形参,联合变 量可以相互赋值。 对联合变量的操作需要特别注意成员的类型属性,不同 类型属性的成员应由不同的分支处理。,11,2. 联合的内存映像 考虑如下初始化于一体的联合声明和联合变量的定义: union u_t int k4; long z; float y; b=1,2,3,4,c; 声明了一个联合名为u_t的联合类型,具有三个成员, 这三个成员是int型数组k4,long型成员z,float型成员y。 第一个成员是数组成员k。同时定义了两个联合变量b 和c,在定义联合变量b的时候对其第一个成员进行了初始化 处理。 该联合占有的内存空间是: sizeof (b)=sizeof (union u)= sizeof (int4)= sizeof (b.k)=16,12,该联合在32位编程模式下的内存布局如下: int型数组k4 long型成员z 8 12 16 float型成员y 4 联合的数据内存分布 在PC微机上数据的存放方式是低尾端形式的, 即short 型16位字节的低8位存放在内存的低地址处, 高8bit存放在内 存的高地址处高尾端的存放方式则相反。 下页的例子说明数据在PC内存中的顺序是低尾端形式。,13,例 强制类型转换显示低尾端的存储格式(8位二进制数的低 位在右边,高位在左边). #include void main() unsigned long m = 0x87654321UL; unsigned char * p=(unsigned char*) ,14,上例低尾端的PC计算上输出结果:21 43 65 87 这样32位整数的8个 4位二进制数的十六进制数数码表示 为: m= h7h6h5h4h3h2h1h0 =87654321 该数以字节即8位bit为最小内存寻址单位的内存存储格 式为(低地址标注在左边): 16进制表示: 低地址 高地址 2进制表示: 低地址 高地址,15,联合的同一片内存可以通过不同的名称索引。对一个成 员的改变直接影响联合中的其它成员的数据状态,对数据的 解释取决于数据的存储格式和模块转换。 例 联合的内存布局和内存数据的解释 #include typedef union u_t char c2; unsigned long k; U; void main() U x = 3,1; /x.c0=3;x.c1=1; 潜在地导致x.c2=0;x.c3=0; printf (“%d,0x%08xt“,x.k,x.k); x. k= 0x67686162UL; printf (“%c,%d,%c,%d; “,x.c0,x.c0,x.c1,x.c1); printf (“%c,%d,%c,%dn “,x.c2,x.c2,x.c3,x.c3); ,16,说明:占4字节的整型数 (4个8位的十六进制数)存贮格 式在微机上是低尾端格式,具有如下的形式(低地址标注在 边,8位二进制数的低位在右边): 高地址 低地址 k= 0x0000|0103 1*16*16+3=259 x.k= 0x67686162UL; 高地址 低地址,17,例浮点数和整型数内存存储格式不同 #include typedef union u_fl float f; long k; Ua; typedef union u_il int f; long k; Ub; struct Sab union float f ; long k; a; Ub b; s= 1.0,2 ; void main() printf(“%1.0f,%dt“,s.a.f,s.b.f); Ua /输出:1,2 20,1092616192 0,40 10,10 20,20,18,联合将不同类型的数据锁定在一块起始地址相同的内存, 通过不同的成员名称或别名来索引内存,以多种方式解释同 一内存数据。 联合具有特殊的数据强制类型转换的能力。 注意: union float f ; long k; a; 是联合类型直接定 义变量,此时联合是无名的。但这种格式不减少访问内层成 员的层次 。,19,3. 无名联合 无名联合在声明时不带联合名,这种声明在C+语言 中具有特殊的含义。 在无名联合中定义的名称超出定界的一对花括号之外, 不能跟同一作用范围其它的变量名冲突,不能有成员函数。 在全局范围定义的无名联合必须声明为静态的,结构中的无 名联合其成员访问控制属性是公共的,不允许存在私有的成 员。 a. 局部的和全局的无名联合 局部范围的无名联合实际上定义的是内存共享的变量, 这些不同类型的变量拥有相同的起始内存地址,内存数据的 有效性取决于最新的二进制状态和对上下文环境的理解。,20,例 无名联合直接定义局部共享的多个变量n,m, x, y。 #include void main (void) union int n; long m; double x; double y; ; printf (“%p,%pt“, /输出: 0065FDF0,0065FDF0 3,3 6.000000,6.000000,21,例 无名联合 static union point_t z; point3d b;定 义静态全局结构变量b和z # include typedef struct double v3; point_t; typedef struct double x,y,z; point3d; typedef union point_t z; point3d b; Ua ; point3d* CrossProduct ( point3d in1, point3d ,22,static union point_t z; point3d b; ; extern point_t * q; const point3d x=1,1,0; point_t* q; void main(void) b.x=0; b.y=2; b.z=1; q= (point_t*)CrossProduct (x,b); if ( b.x=z.v0 ,23,/输出: b= 1.0,-1.0, 2.0 q= 1.0,-1.0, 2.0 a= 1.0, 2.0, 3.0 上面的无名联合定义静态全局结构变量b和z,b和z 是 同一片集合内存的两个别名,相应的结构成员也一对一的彼 此相配。 两个结构本身描述的是空间点的坐标,只是成员名称 不同;将这样的结构变量联合在一起达到内存数据充分共享. 静态的全局变量可以通过外部连接属性的全局指针在不 同模块中传递信息。 联合可用于接口设计,两个课题组建立了相同的数据结 构例如 :point_t和point3d,只是其中的成员名称不同,可 以将其联合在一起。,24,b. 结构范围中的无名联合 可以在结构的声明中引入无名联合,无名联合包含的数 据成员在内存中共享一片内存空间,无名联合中单独的成员 直接作为结构成员的相对独立部分。联合变量可以作为结构 的成员,这相当于嵌入的对象,对于嵌入对象需要层层访 问。无名联合减少访问成员的层次,可以直接访问无名联合 中的成员。联合提供一种课题组之间相同数据结构(即成员 个数、类型、次序相同只是名称不同)的接口技术。设课题 组A和B的结构类型为: typedef struct person_a int n; float f; char *s; A; typedef struct person_b int number; float income; char * name; B;,25,A结构和B结构是一致的。并在相关的结构上相应地开 发一套算法。将这两个结构通过无名联合并置在一起,则可 以发挥各自的特点。下面的例子说明无名联合的这一用法。 例 结构范围中的无名联合实现不同课题组之间的数据接口 # include # include typedef struct a_t union int n; int number; ; union float f; float income; ; union char *s; char *name; ; A, B;,26,int SeqFind(const B s ,int n,float key) for(int i=0;in;i+) if (si.income=key) return i; return -1; int SeqFind (const A s ,int n,const char* key) for (int i=0;in;i+) if (strcmp(si.s,key)=0) return i; return -1; ,27,void InitData (B b ,int n ,float f , char (*s)20,int num=5) for(int i=0;in,p-f,p-s); printf (“n“); ,28,const int N=5; static char caN20=“Hisen“,“Boir“,“Rose“,“Bush“,“Kelin“; void main() static int naN=11,22,33,44,55; float xaN=88,90,70,80,60; A sa N; InitData(sa,na,xa,ca,N); show (sa,N); int k=SeqFind (sa,N,“Rose“); if (k!=-1) show (sak); k=SeqFind (sa,N,60); if (k!=-1) show (sak); ,29,/输出结果: 11,88.0,Hisen,22,90.0,Boir, 33,70.0,Rose,44,80.0,Bush, 55,60.0,Kelin,33,70.000000,Rose 55,60.000000,Kelin 联合可实现内存的共用与数据的共用,更可实现不同 类型数据互相排斥地占用同一内存或相同内存段互异数据的 不共用。 union在一些介绍C语言的中文书中被译为共用体,这 多少有失union原有的丰富内涵。 术语翻译应切近原意,而其确切含义则需详细解释。,30,十、数据的引用类型转换 基本变量之间存在类型转换关系。 例如: float f; long l=7788; f=(float)l; l=(long)f; 表达式语句f=(float)l;意味着将long型变量l的值在相 应的内存单元取出,经过类型转换模块,然后将结果送入f 变量表示的存储单元中,以浮点格式存储。 对于同类型的结构变量或联合变量编译器允许赋值运 算。,31,设存在两个结构的声明为: struct sb sb结构数据成员列表; ; struct sa sa结构数据成员列表; ; 定义结构变量a,a1,b,b1分别如下: struct sa a,a1; struct sb b,b1; a=a1; b=b1; 赋值表达式语句a=a1表示结构变量a1的数据状态赋给 对应的结构变量a,相当于系统进行了函数调用: memcpy (,32,但不同类型的结构变量的赋值如 a=b1 则是不允许的。 因为编译器并未提供不同类型结构变量之间赋值的缺省 运算。 同样对于类型转换: a=(struct s)b1; 系统也会提出错误警告。系统对于不同结构变量的数值 转换无论是隐含的或显式都没有提供缺省的保证。但C+允 许引用形式的类型转换。 引用形式类型转换的一般形式为: (目标类型名&)源变量 (type&)variable 引用类型转换的结果为左值。,33,对于两个结构变量a,b,一个具体的引用类型转换的语 法格式如下: a = (struct sa 赋值拷贝映射的原则是将源数据内存的状态根据目标集 合的长度复制给目标所占用的内存。如果sizeof(sb)大于 sizeof(sa),那么转换 b = (sb&)a将导致对集合数据a的越 界,反之如a = (sa&)b则对长的源数据b前面的sizeof(sa)个 元素进行了复制。引用形式类型转换表示了集合数据间的直 接映射,当然也可以对简单变量进行引用的类型转换。,34,例 结构变量的类型转换与复制 #include typedef struct sa int m; A; typedef struct sb int x; int y; B; void show (B /程序输出:b=1,4 b=8, 6684216,35,十一、位域或位字段 位字段(bit field)是特殊之至的数据结构,该结构将整 型变量占有的内存按位进行细分,细分的位数可以大小不 等,具体的bit位置通过若干成员来索引,成员的数据类型通 过char , int,short ,unsigned short,long等整型或梅举类界 定。 其中b1,b2,bn表示成员,count1, count2, countn表示 相应成员占有的bit位的个数。,36,方括号包括的项表示可以省略,格式如下: struct bit_t int b1 : count1; int

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论