ImageVerifierCode 换一换
格式:DOCX , 页数:21 ,大小:25.93KB ,
资源ID:20975251      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/20975251.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(struct和unionWord文件下载.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

struct和unionWord文件下载.docx

1、注意,printf的%u转换说明表示无符号数,sizeof的值是size_t类型的,是某种无符号整型。为什么编译器要这样处理呢?有一个知识点我此前一直回避没讲,那就是大多数计算机体系统结构对于访问内存的指令是有限制的,在32位平台上,访问4字节的指令(比如上面的movl)所访问的内存地址应该是4的整数倍,访问两字节的指令(比如上面的movw)所访问的内存地址应该是两字节的整数倍,这称为对齐(Alignment)。以前举的所有例子中的内存访问指令都满足这个限制条件,读者可以回头检验一下。如果指令所访问的内存地址没有正确对齐会怎么样呢?在有些平台上将不能访问内存,而是引发一个异常,在x86平台上倒

2、是仍然能访问内存,但是不对齐的指令执行效率比对齐的指令要低,所以编译器在安排各种变量的地址时都会考虑到对齐的问题。对于本例中的结构体,编译器会把它的基地址对齐到4字节边界,也就是说,ebp-0x10这个地址一定是4的整数倍。s.a占一个字节,没有对齐的问题。s.b占两个字节,如果s.b紧挨在s.a后面,它的地址就不能是两字节的整数倍了,所以编译器会在结构体中插入一个填充字节,使s.b的地址也是两字节的整数倍。s.c占4字节,紧挨在s.b的后面就可以了,因为ebp-0xc这个地址也是4的整数倍。那么为什么s.d的后面也要有填充位填充到4字节边界呢?这是为了便于安排这个结构体后面的变量的地址,假如

3、用这种结构体类型组成一个数组,那么后一个结构体只需和前一个结构体紧挨着排列就可以保证它的基地址仍然对齐到4字节边界了,因为在前一个结构体的末尾已经有了填充字节。事实上,C标准规定数组元素必须紧挨着排列,不能有空隙,这样才能保证每个元素的地址可以按“基地址+n元素大小”简单计算出来。合理设计结构体各成员的排列顺序可以节省存储空间,例如上例中的结构体改成这样就可以避免产生填充字节:struct char a; char d; short b; int c; s;此外,gcc提供了一种扩展语法可以消除结构体中的填充字节: _attribute_(packed) s;这样就不能保证结构体成员的对齐了,

4、在访问b和c的时候可能会有效率问题,所以除非有特别的理由,一般不要使用这种语法。以前我们使用的数据类型都是占几个字节,最小的类型也要占一个字节,而在结构体中还可以使用Bit-field语法定义只占几个bit的成员。下面这个例子出自王聪的网站(www.wangcong.org):例 19.4. Bit-fieldtypedef struct unsigned int one:1; unsigned int two:3; unsigned int three:10; unsigned int four:5; unsigned int :2; unsigned int five:8; unsigne

5、d int six: demo_type;int main(void) demo_type s = 1, 5, 513, 17, 129, 0x81 ;sizeof demo_type = %un, sizeof(demo_type);values: s=%u,%u,%u,%u,%u,%un, s.one, s.two, s.three, s.four, s.five, s.six);s这个结构体的布局如下图所示:图 19.6. Bit-field的存储布局Bit-field成员的类型可以是int或unsigned int,表示有符号数或无符号数,但不表示它像普通的int型一样占4个字节,它后

6、面的数字是几就表示它占多少个bit,也可以像unsigned int :这样定义一个未命名的Bit-field,即使不写未命名的Bit-field,编译器也有可能在两个成员之间插入填充位,如上图的five和six之间,这样six这个成员就刚好单独占一个字节了,访问效率会比较高,这个结构体的末尾还填充了3个字节,以便对齐到4字节边界。以前我们说过x86的Byte Order是小端的,从上图中one和two的排列顺序可以看出,如果对一个字节再细分,则字节中的Bit Order也是小端的,因为排在结构体前面的成员(靠近低地址一边的成员)取字节中的低位。关于如何排列Bit-field在C标准中没有详细

7、的规定,这跟Byte Order、Bit Order、对齐等问题都有关,不同的平台和编译器可能会排列得很不一样,要编写可移植的代码就不能假定Bit-field是按某一种固定方式排列的。Bit-field在驱动程序中是很有用的,因为经常需要单独操作设备寄存器中的一个或几个bit,但一定要小心使用,首先弄清楚每个Bit-field和实际bit的对应关系。和前面几个例子不一样,在上例中我没有给出反汇编结果,直接画了个图说这个结构体的布局是这样的,那我有什么证据这么说呢?上例的反汇编结果比较繁琐,我们可以通过另一种手段得到这个结构体的内存布局。C语言还有一种类型叫联合体,用关键字union定义,其语法

8、类似于结构体,例如:例 19.5. 联合体typedef union unsigned int one: unsigned int two: unsigned int three: unsigned int four: unsigned int : unsigned int five: unsigned int six: bitfield; unsigned char byte8; demo_type u = 1, 5, 513, 17, 129, 0x81 ; u=%u,%u,%u,%u,%u,%un u.bitfield.one, u.bitfield.two, u.bitfield.th

9、ree, u.bitfield.four, u.bitfield.five, u.bitfield.six);hex dump of u: %x %x %x %x %x %x %x %x n u.byte0, u.byte1, u.byte2, u.byte3, u.byte4, u.byte5, u.byte6, u.byte7);一个联合体的各个成员占用相同的内存空间,联合体的长度等于其中最长成员的长度。比如u这个联合体占8个字节,如果访问成员u.bitfield,则把这8个字节看成一个由Bit-field组成的结构体,如果访问成员u.byte,则把这8个字节看成一个数组。联合体如果用In

10、itializer初始化,则只初始化它的第一个成员,例如demo_type u = 1, 5, 513, 17, 129, 0x81 ;初始化的是u.bitfield,但是通过u.bitfield的成员看不出这8个字节的内存布局,而通过u.byte数组就可以看出每个字节分别是多少了。C/C+中的联合 union减小字体 增大字体 联合(union)在C/C+里面见得并不多,但是在一些对内存要求特别严格的地方,联合又是频繁出现,那么究竟什么是联合、怎么去用、有什么需要注意的地方呢?就这些问题,我试着做一些简单的回答,里面肯定还有不当的地方,欢迎指出!1、什么是联合?“联合”是一种特殊的类,也是一

11、种构造类型的数据结构。 在一个“联合”内可以定义多种不同的数据类型, 一个被说明为该“联合”类型的变量中,允许装入该“联合”所定义的任何一种数据,这些数据共享同一段内存,已达到节省空间的目的(还有一个节省空间的类型:位域)。 这是一个非常特殊的地方,也是联合的特征。另外,同struct一样,联合默认访问权限也是公有的,并且,也具有成员函数。2、联合与结构的区别?“联合”与“结构”有一些相似之处。但两者有本质上的不同。在结构中各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和(空结构除外,同时不考虑边界调整)。而在“联合”中,各成员共享一段内存空间, 一个联合变量的长度等于各成员中最

12、长的长度。应该说明的是, 这里所谓的共享不是指把多个成员同时装入一个联合变量内, 而是指该联合变量可被赋予任一成员值,但每次只能赋一种值, 赋入新值则冲去旧值。3、如何定义?例如:union testtest() int office;char teacher;定义了一个名为test的联合类型,它含有两个成员,一个为整型,成员名为office;另一个为字符数组,数组名为teacher。联合定义之后,即可进行联合变量说明,被说明为test类型的变量,可以存放整型量office或存放字符数组teacher。4、如何说明?联合变量的说明有三种形式:先定义再说明、定义同时说明和直接说明。以test类型

13、为例,说明如下:1) union testunion test a,b; /*说明a,b为test类型*/2) union test a,b;3) union经说明后的a,b变量均为test类型。a,b变量的长度应等于test的成员中最长的长度,即等于teacher数组的长度,共5个字节。a,b变量如赋予整型值时,只使用了4个字节,而赋予字符数组时,可用5个字节。5、如何使用?对联合变量的赋值,使用都只能是对变量的成员进行。联合变量的成员表示为:联合变量名.成员名例如,a被说明为test类型的变量之后,可使用a.class、a.office不允许只用联合变量名作赋值或其它操作,也不允许对联合变

14、量作初始化赋值,赋值只能在程序中进行。还要再强调说明的是,一个联合变量,每次只能赋予一个成员值。换句话说,一个联合变量的值就是联合变员的某一个成员值。6、匿名联合匿名联合仅仅通知编译器它的成员变量共同享一个地址,而变量本身是直接引用的,不使用通常的点号运算符语法.例如:#include void main()unionint test;char c;test=5;c=a;std:coutibyte0 pad0 pad1 pad2 -HIGH;0x87654321按内存从低到高的存放顺序: 0x21 0x43 0x65 0x87, 可见byte0对应到0x21。所以通过判断dword中第一个字节

15、dword.bytes.byte0是否与0x21相等就可以看出是否是little endian。EXAMPLE 2typedef union _studentunsigned int all;/*all可以同时清理或设置info中的所有内容*/structunsigned int pad: 7;/* 7 bit */unsigned int used: 1;/* 高位 */ personal_id: class_id: 3; subject_id:6;score:/*低位*/info;student;#define MAX_STUDENT_NUM 100students;student_dat

16、abaseMAX_STUDENT_NUM=0;int add_to_database(unsigned int data); find_from_database(unsigned int personal_id); delete_from_database(unsigned int personal_id);voidprint_database(void);void print_student(unsigned int data);int add_to_database(unsigned int data)student stu;int i;for(i=0;MAX_STUDENT_NUM;i

17、+)stu.all = student_databasei;if(!stu.info.used)stu.all = data;stu.info.used= 1;student_databasei = stu.all;return 1;return 0;int find_from_database(unsigned int personal_id)if(stu.info.used & stu.info.personal_id=personal_id)return stu.all;return -1;void print_student(unsigned int data)stu.all = da

18、ta;printf(personal id %d,class id %d,subject id %d,score %dnstu.info.personal_id,stu.info.class_id,stu.info.subject_id,stu.info.score);void print_database(void)if(stu.info.used)print_student(stu.all);int main(int argc, char *argv)student jack,jone;jack.all= 0;jack.info.personal_id= 102;jack.info.cla

19、ss_id = 2;/*class 2*/jack.info.subject_id = 2;/*English*/jack.info.score = 50;/*fouled*/add_to_database(jack.all);jone.all = 0;jone.info.personal_id= 88;jone.info.class_id/*calss 2*/jone.info.subject_id/*English*/jone.info.score = 73;/*passed*/add_to_database(jone.all);jack.all = find_from_database(

20、jack.info.personal_id);if(jack.all0)no such student with id %dn,jone.info.personal_id);elsefound!);print_student(jack.all);print_database();运行结果: personal id 102,class id 2,subject id 2,score 50personal id 102,class id 2,subject id 2,score 50personal id 88,class id 2,subject id 2,score 732. union巧妙地实现多字化节数据类型之间的转化在涉及音视频编解码算法中,经常会涉及一些数据压缩、声音解码、图象的缩放等问题。这里通过一个例子来推荐

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1