C语言中联合和结构有什么区别Word格式.docx
《C语言中联合和结构有什么区别Word格式.docx》由会员分享,可在线阅读,更多相关《C语言中联合和结构有什么区别Word格式.docx(8页珍藏版)》请在冰豆网上搜索。
%c\t%d\t%.2f\n"
dl.c._data,dl.i_data,dl.f,data);
printf("
%d\n'
sizeof(dl));
%p\t%p\t%p\t%p\n"
&
dl.c_data,&
dl.i_data,&
dl.f.data,&
dl);
}
执行该程序输出结果如下:
?
?
3.7(?
表示无意义)
4
FFD6FFD6FFD6FFD6
说明:
(1)该程序中,首先定义一个联合,其名为data,它有3个成员,分别是三种不同类型。
又定义联合变量d3,并给它的三个成员分别赋值。
当使用printf()函数输出dl的三个成员的值时,前两个成员输出值是无意义的,只有最后一个成员是有意义的,其值为3.7.这说明:
某一时刻一个联合变量中只有一个成员起作用,其他成员不起作用。
(2)输出,SizeoE(dl)的值为4,这说明联合变量d1占内存4个字节。
在多个联合成员共占一个内存地址时,该地址所指向的内存空间是所有成员中占内存空间最大的成员所占的内存空间。
该例中的三个成员所占内存字节数分别为1.2和4,最大的是4,因此,联合变量dl所占内存空间为4个字节。
(3)使用printf()函数分别输出联合变量dl的三个成员的内存地址都是相同的,并且与联合变量dl的地址值也是相同的,可见联合变量各成员是共址的。
共用体
构造数据类型,也叫联合体
用途:
使几个不同类型的变量共占一段内存(相互覆盖)
结构体是一种构造数据类型
把不同类型的数据组合成一个整体-------自定义数据类型
---------------------------------------------------------------
结构体变量所占内存长度是各成员占的内存长度的总和。
共同体变量所占内存长度是各最长的成员占的内存长度。
共同体每次只能存放哪个的一种!
!
共同体变量中起作用的成员是尊后一次存放的成员,
在存入新的成员后原有的成员失去了作用!
Structure与Union主要有以下区别:
1.struct和union都是由多个不同的数据类型成员组成,但在任何同一时刻,union中只存放了一个被选中的成员,而struct的所有成员都存在。
在struct中,各成员都占有自己的内存空间,它们是同时存在的。
一个struct变量的总长度等于所有成员长度之和。
在Union中,所有成员不能同时占用它的内存空间,它们不能同时存在。
Union变量的长度等于最长的成员的长度。
2.对于union的不同成员赋值,将会对其它成员重写,原来成员的值就不存在了,而对于struct的不同成员赋值是互不影响的。
举一个例子:
例:
#include<
stdio.h>
voidmain()
{
union{
/*定义一个联合*/
inti;
struct{
/*在联合中定义一个结构*/
charfirst;
charsecond;
}half;
}number;
number.i=0x4241;
/*联合成员赋值*/
printf("
%c%c\n"
number.half.first,number.half.second);
number.half.first='
/*联合中结构成员赋值*/
number.half.second='
b'
%x\n"
number.i);
system("
pause"
);
}
输出结果为:
AB
6261
分析:
union的成员是共用内存的
union{
inti;
struct{
charfirst;
charsecond;
}half;
}number;
number.i=0x4241;
在这里i和half结构是共用内存
number.i=0x4241给i赋值后,内存中以二进制存储0100001001000001
按顺序对应到结构中
halt.first=01000010
转换成10进制就是66(字母A的asc码)
halt.second=01000001转换成10进制是65
(字母B的asc码)
所以输出后就是AB
下面同理了
==========================================================================
第一题:
#include<
union
{
charx[2];
}a;
a.x[0]=10;
a.x[1]=1;
%d"
a.i);
}
答案:
266
第二题:
main()
union{/*定义一个联合*/
struct{/*在联合中定义一个结构*/
/*联合成员赋值*/
number.half.first,mumber.half.second);
number.half.first='
/*联合中结构成员赋值*/
number.half.second='
getch();
AB6261
C语言中的联合体(UNION)的概念是,联合体中的多种数据类型共享同一个内存空间。
就拿你举的例子来说:
在联合体a中定义了两种数据类型,字符数组x以及整形变量i.其中整形变量是16位的,数组大小为2的字符数组为8X2=16位。
如此一来,编译器便会为联合体a在内存中开辟一个16位的空间,这个空间里存储联合体的数据,但是这个空间只有16位,它既是整形变量的数据,也是字符数组的数据。
如果你的程序从字符数组的角度解析这个空间,那么它就是两个字符,如果你的程序从整型的角度解析这个空间,那么它就是一个整数。
以你的程序为例子,现在已经开辟了一个16位的空间,然后我们假定现在空间还没有被赋值,为:
0000000000000000
那么在运行完代码
a.x[0]=10;
a.x[1]=1;
之后,16位的空间变为:
0000011000000001
然后程序运行
就是把联合体a当成一个整数来解析,而不是字符串数组。
那么这样一来,程序就把这16位变成了一个完整的整数:
(0000000100000110)二进制=(266)十进制
注意,你可以看到程序在把16位弄成整数的时候把后面八位放在了前面,前面八位放在了后面。
这个反序是计算机存储结构造成的,这个和联合体没有直接关系。
如果感兴趣的话可以参考汇编语言。
就是这个道理。
第二个例子同样,
struct{/*在联合中定义一个结构*/
定义了联合体number,这个联合体有两种数据类型,整形i(16位),以及一个结构体(structhalf)(2个char,16位)。
所以编译器为这个联合体开辟一个16位的空间:
0000000000000000
然后赋值:
这个时候,联合体以整形的身份出现,16位的空间将被整体认为是一个整数赋值。
注意(0x4241)(16进制)=(0100001001000001)二进制。
还记得刚才说的,计算机存储的时候是反着存的吗,先存低位,再存高位(参考汇编语言),因此16位地址被赋值位
0100000101000010
然后
实际上是把16位空间以结构体half的角度解析,也就是两个char.
那么第一个:
number.half.first=(01000001)二进制=(65)十进制=A(ASCII码)
同理number.half.second=B(ASCII码)
当然后头又给first和second赋值位"
a"
和"
b"
这样会把16位空间弄成是:
0110000101100010
然后用
就是把16位看成整数,记住高地位反过来
(0110001001100001)二进制=
(0X6261)16进制
所以结果就是:
0x6261.
最后记得按任意键结束程序。
=========================================================================
试题1:
请写一个C函数,若处理器是Big_endian的,则返回0;
若是Little_endian的,则返回1
解答:
intcheckCPU()
{
unionw
{
inta;
charb;
}c;
c.a=1;
return(c.b==1);
}
剖析:
嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。
采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。
例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
内存地址
存放内容
0x4000
0x34
0x4001
0x12
而在Big-endian模式CPU内存中的存放方式则为:
32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为:
0x78
0x56
0x4002
0x4003
联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。
如果谁能当场给出这个解答,那简直就是一个天才的程序员。
试题2:
写一个函数返回1+2+3+…+n的值(假定结果不会超过长整型变量的范围)
intSum(intn)
return((long)1+n)*n/2;
//或return(1l+n)*n/2;
对于这个题,只能说,也许最简单的答案就是最好的答案。
下面的解答,或者基于下面的解答思路去优化,不管怎么“折腾”,其效率也不可能与直接return(1l+n)*n/2相比!
longsum=0;
for(inti=1;
i<
=n;
i++)
sum+=i;
returnsum;