完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
结构体与联合体是C语言的常见数据类型,可对C的基本数据类型进行组合使之能表示复杂的数据结构,意义深远,是优异代码的必备工具。
一. struct与 union的基本用法,在语法上union与struct相同,因此只以struct为例 1.1 基本用法:struct AA{ int a; int b;}; //结构体的声明和定义 struct AA s1; //变量的声明和定义 s1.a=3; //变量的使用: 复制代码1.2 在声明结构体的同时定义变量:struct AA{int a; int b}s2={1, 2}; //此处AA为可选项,初始化部分为可选 s2.a=5; //变量的使用 复制代码1.3 使用 typedef 来简化struct的类型说明:typedef struct AA{int a; int b;}SAA; SAA s3, s4; //变量的声明和定义 s3.a=8; //变量的使用 复制代码1.4 使用时尤其注意后面的分号,必不可少; 二. struct 与 union的区别 2.1 struct中的成员是按顺序依次排列,互相独立,在排列时引入了对齐问题(2.2);而union中的成员共用一块内存,起始地址都是相同的,即union中的成员是对同一地址的多个引用、对同一地址的多种表达方法。 2.2 struct的对齐问题 对齐问题即struct中每个成员起始地址的分配。为了可以快速访问到每个成员,(以EW430为例)编译器根据成员的类型放到合适的地址上,默认为2字节对齐。如: Struct AA{char c; int d;}aa; 假设aa被分配在地址N上,并且N为偶数,则aa.c的地址为N,aa.d的地址为N+2,而N+1地址未使用被浪费了。 对齐字节大小的指定:通过#pragma pack(n)来指定对齐字节的大小,n为某些常量(EW430中可取1,2,4,8,16),指定以n字节对齐。通常使用编译器默认的对齐大小最为适宜。如果指定对齐大小为1字节对齐,以上面的结构体变量aa为例,aa.c地址为N,aa.d地址为N+1,是个奇数地址,因为430在奇数地址只能读取一个字节,因此要访问d成员需要读取两次才能完成,后果是代码变长、速度变慢。 三. 匿名结构体与联合体 匿名结构体和联合体,即没有名字的结构体或者联合体,这种结构体(或联合体)无法通过.与->操作符引用(因为它所属的结构体或联合体没有名字,无法应用),而像暴露在外面一样,与外层作用域相同,可直接使用。 3.1 C标准中提及的匿名结构体和联合体(草稿原文引用)(C标准中提及的匿名结构(联合)体应该只适用于有名结构体(联合)中的匿名结构(联合)体成员)struct v{ union{ //匿名联合体 struct {int i, j;}; //匿名结构体 struct {long k, l;}w; }; int m; }v1; v1.i=2; //合法,匿名结构体的成员被直接使用 v1.k=3;//非法,有名字的结构体需要引用他的名字,如下 v1.w.k=5; //合法 复制代码3.2 IAR中的匿名结构体和联合体 IAR中的匿名结构体和联合体可以具有全局作用域,因此结构体或联合体中的成员可以作为全局变量使用,但却兼具结构体或者联合体的属性。 (1) IO430.h系列头文件的寄存器声明方式: 如: __no_init volatile union { unsigned short SFRIE1; /* Interrupt Enable 1 */ struct { unsigned short WDTIE : 1; /* WDT Interrupt Enable */ unsigned short OFIE : 1; /* Osc Fault Enable */ unsigned short : 1; unsigned short VMAIE : 1; /* Vacant Memory Interrupt Enable */ unsigned short NMIIE : 1; /* NMI Interrupt Enable */ unsigned short ACCVIE : 1; /* Flash Access Violation Interrupt Enable */ unsigned short JMBINIE : 1; /* JTAG Mail Box input Interrupt Enable */ unsigned short JMBOUTIE : 1; /* JTAG Mail Box output Interrupt Enable */ }SFRIE1_bit; } @0x0100; 复制代码说明:[1]. SFRIE1和SFRIE1_bit具有全局变量的性质,可以直接被引用。 [2]. SFRIE1和SFRIE1_bit在同一联合体中,根据联合体的性质,他们共享同一地址,即对同一寄存器不同访问方式,SFRIE1对整个寄存器操作,SFRIE1_bit可对某位操作,如: SFRIE1 |= 0x0001;和SFRIE1_bit.WDTIE = 1;具有相同效果。 [3]. 冒号(:)与整数称之为位域,使用位域表达的变量使用同一数据中的不同位,并按顺序排列。整数表示这个变量占用多少位。没有名字的位域不能被引用到,一般用来保留未使用到的位(占位作用)。 (2) 在应用程序中也可以使用此特性来实现一些功能。 记得某位网友曾提出过这样的问题,要高效的使用一个整数的高8位和低8位,则可以用如下代码解决:union { unsigned int num; struct { unsigned char nLow; unsigned char nHigh; }; }; 复制代码或者union { unsigned int num; struct { unsigned int nLow :8; unsigned int nHigh :8; }; }; int a = num; int b = nLow; int c = nHigh; 复制代码非常好的解决方案,只占用一个整数的空间,可以对高8位、低8位、整个16位引用而不需要计算。 (3) 联合体中的位域(补充)union { unsigned int z; unsigned int z1 : 1; unsigned int z2 : 2; unsigned int z3 : 3; unsigned int z4 : 4; }; z = 0xFFFF; a = z1; b = z2; c = z3; 复制代码结果:a = 1, b = 3, c = 7; (4)结构体中的位域长度0 (补充)union ZZ{ unsigned int z1 : 1; unsigned int z2 : 1; unsigned int z3 : 1; unsigned int z4 : 1; unsigned int : 0; unsigned int z6 : 1; }zz; 复制代码长度为0的位域是通知编译器不要在以前的单元上分配位域了,代表着一个单元的位域分配结束,这个长度为0的位域不能有名字。以后的位域分配要新开辟一个单元。 以上的例子中,z1, z2, z3, z4共用一个unsigned int中的4个bit,z6单独使用一个unsigned int; 此结构体共占用两个unsigned int空间 |
|
相关推荐
4 个讨论
|
|
只有小组成员才能发言,加入小组>>
3036个成员聚集在这个小组
加入小组2935 浏览 1 评论
MSP430FR5994 使用库函数 定时器触发AD问题请教
3613 浏览 2 评论
请问怎么把下面51单片机的代码改成msp430 g2 pocket的代码,还有改下时间变成30秒
2346 浏览 1 评论
4810 浏览 1 评论
2576 浏览 1 评论
1335浏览 3评论
MSP430FR5994 使用库函数 定时器触发AD问题请教
3614浏览 2评论
2937浏览 1评论
1522浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-2 15:31 , Processed in 1.383773 second(s), Total 63, Slave 52 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号