union

更新时间:2022-12-28 06:30:00 阅读: 评论:0


2022年12月28日发(作者:bec中级听力下载)

union的⽤法以及struct的初始化

在C/C++程序的编写中,当多个基本数据类型或复合数据结构要占⽤同⼀⽚内存时,我们要使⽤联合体;当多种类型,多个对象,多个事物

只取其⼀时(我们姑且通俗地称其为“n选1”),我们也

可以使⽤联合体来发挥其长处。⾸先看⼀段代码:

unionmyun

{

struct{intx;inty;intz;}u;

intk;

}a;

intmain()

{

a.u.x=4;

a.u.y=5;

a.u.z=6;

a.k=0;

printf("%d%d%dn",a.u.x,a.u.y,a.u.z);

return0;

}

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是Littleendian还是Bigendian模式?

分析:

作为⼀个计算机相关专业的⼈,我们应该在计算机组成中都学习过什么叫Littleendian和Bigendian。Littleendian和Bigendian是CPU存

放数据的两种不同顺序。对于整型、长整型等数据类型,Bigendian认为第⼀个字节是最⾼位字节(按照从低地址到⾼地址的顺序存放数据

的⾼位字节到低位字节);⽽Littleendian则相反,它认为第⼀个字节是最低位字节(按照从低地址到⾼地址的顺序存放数据的低位字节到

⾼位字节)。

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

0x120x340xab0xcd

如果我们去读取⼀个地址为0x0000的四个字节变量,若字节序为big-endian,则读出结果为0x1234abcd;若字节序位little-endian,则读出

结果为0xcdab3412。如果我们将0x1234abcd写⼊到以0x0000开始的内存中,则Littleendian和Bigendian模式的存放结果如下:

地址0x00000x00010x00020x0003

big-endian0x120x340xab0xcd

little-endian0xcd0xab0x340x12

⼀般来说,x86系列CPU都是little-endian的字节序,PowerPC通常是Bigendian,还有的CPU能通过跳线来设置CPU⼯作于Little

endian还是Bigendian模式。

解答:

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

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

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

typedefunsignedcharBYTE;

intmain(intargc,char*argv[])

{

unsignedintnum,*p;

p=#

num=0;

*(BYTE*)p=0xff;

if(num==0xff)

{

printf("Theendianofcpuislittlen");

}

el//num==0xff000000

{

printf("Theendianofcpuisbign");

}

return0;

}

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

有更好的办法呢?我们知道,union的成员本⾝就被存放在相同的内存空间(共享内存,正是union发挥作⽤、做贡献的去处),因此,我

们可以将⼀个CHAR/BYTE数据和⼀个整型数据同时作为⼀个union的成员,得出

如下答案:

intcheckCPU()

{

{

unionw

{

inta;

charb;

}c;

c.a=1;

return(c.b==1);

}

}

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

staticunion{charc[4];unsignedlongmylong;}endian_test={{'l','?','?','b'}};

#defineENDIANNESS((char)endian_)

Linux的内核作者们仅仅⽤⼀个union变量和⼀个简单的宏定义就实现了⼀⼤段代码同样的功能!由以上⼀段代码我们可以深刻领会到Linux

源代码的精妙之处!(如果ENDIANNESS=’l’表⽰系统为littleendian,

为’b’表⽰bigendian)

试题⼆:假设⽹络节点A和⽹络节点B中的通信协议涉及四类报⽂,报⽂格式为“报⽂类型字段+报⽂内容的结构体”,四个报⽂内容的结构体

类型分别为STRUCTTYPE1~STRUCTTYPE4,请编写程序以最简单的⽅式组

织⼀个统⼀的报⽂数据结构。

分析:

报⽂的格式为“报⽂类型+报⽂内容的结构体”,在真实的通信中,每次只能发四类报⽂中的⼀种,我们可以将四类报⽂的结构体组织为⼀个

union(共享⼀段内存,但每次有效的只是⼀种),然后和报⽂类型字段统⼀组织成⼀个报⽂数据结构。

解答:

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

typedefunsignedcharBYTE;

//报⽂内容联合体

typedefuniontagPacketContent

{

STRUCTTYPE1pkt1;

STRUCTTYPE2pkt2;

STRUCTTYPE3pkt1;

STRUCTTYPE4pkt2;

}PacketContent;

//统⼀的报⽂数据结构

typedefstructtagPacket

{

BYTEpktType;

PacketContentpktContent;

}Packet;

写了⼀个⼩例⼦,将union和struct相结合。

#include

structend{

intend;

union{

charc;

intk;

}myun;

/*unionmyun{

charc;

intk;

}a;struct中的union可以⽤这两种⽅法来声明*/

};

intmain()

{

structendend1={

.end=24,

.myun={'k'},

};//注意struct的初始化,各个成员初始化完毕之后使⽤‘,’⽽不是‘;’。

printf("%d%c%dn",,.c,.k);

return0;

}

本文发布于:2022-12-28 06:30:00,感谢您对本站的认可!

本文链接:http://www.wtabcd.cn/fanwen/fan/90/45199.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:韩国男子组合
标签:union
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图