在使用共用体类型变量的数据时要注意:
在共用体类型变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原胡的成员就失去了作用,如:
a.i=1;a,c='a';a.f=1.3;在完成了三个赋值运算以后,只有a.f是有效的,其他的忆被覆盖了。
共用体类型变量可以向另一个相同共用体类型的变量赋值。
此外,共用类型变量可以作为参数传递给函数,也可以使用地址传递方式把共用体类型变量的地址作为参数在函数间传递。
在程序中经常使用结构体与共用体相互嵌套的形式。
即共用体类型的成员可是结构体类型,或结构体类型的成员是共用体类型。
例如,下列结构何体类型datas的第三个成员是共用体类型:
structdatas
{
char*ps;
inttype;
union
{
floatfdata;
intidata;
charcdata;
}udata;
};
结构体与共用体的大小
A.结构体与共用体
一、结构体(struct)
1.定义:
结构体是由一系列具有相同数据类型或不同数据类型的数据构成的数据集合。
2.例子:
structstudent
{
int num;
charname[20];
};
注意不要忽略最后的分号
3.定义结构体类型变量的方法:
strcut studentstudent1,student2;
4.大小:
(1)空结构体的大小为1byte.
(2)结构体的大小要是最严格,看下面详细介绍。
如:
structstudent
{
intnum;
charname;
};
占据的内存空间为8个byte。
structstudent
{
intnum;
charname;
charmark;
};
大小也是8个Byte。
按内存对齐方式说,应该是12个字节,所以这里有些不明白。
注意:
结构体变量可以有这样的赋值:
A=B;
二、共用体(union)
1.定义:
union维护足够的空间来放置多个数据成员中的“一种”,而不是为每一个数据成员配置 空 间,
在union中所有的数据成员公用一个空间,同一时间只能存储其中的一个数据成员,所有的成员具有相
同的起始地址。
举例:
uniondata
{
inti;
charch;
floatf;
}
大小为4个字节。
2.引用方式:
不能引用共用体的变量,只能引用变量中的成员。
如a.i,a.ch.
B.结构体的大小
运算符sizeof可以计算出给定类型的大小,对于32位系统来说,
sizeof(char)=1;sizeof(int)=4。
基本数据类型的大小很好计算,我们来看一下如何计算构造数据类型的大小。
C语言中的构造数据类型有三种:
数组、结构体和共用体。
数组是相同类型的元素的集合,只要会计算单个元素的大小,整个数组所占空间等于基础元素大小乘上元素的个数。
结构体中的成员可以是不同的数据类型,成员按照定义时的顺序依次存储在连续的内存空间。
和数组不一样的是,结构体的大小不是所有成员大小简单的相加,需要考虑到系统在存储结构体变量时的地址对齐问题。
看下面这样的一个结构体:
structstu1
{
int i;
char c;
int j;
};
类型对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
?
?
Char 偏移量必须为sizeof(char)即1的倍数
?
?
Short 偏移量必须为sizeof(short)即2的倍数
?
?
int?
?
偏移量必须为sizeof(int)即4的倍数
?
?
float?
?
偏移量必须为sizeof(float)即4的倍数
?
?
double?
偏移量必须为sizeof(double)即8的倍数
实际上,由于存储变量时地址对齐的要求,编译器在编译程序时会遵循两条原则:
一、结构体变量中成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)
二、结构体大小必须是所有成员大小的整数倍。
对照第一条,上面的例子中前两个成员的偏移量都满足要求,但第三个成员的偏移量为5,并不是自身(int)大小的整数倍。
编译器在处理时会在第二个成员后面补上3个空字节,使得第三个成员的偏移量变成8。
对照第二条,结构体大小等于最后一个成员的偏移量加上其大小,上面的例子中计算出来的大小为12,满足要求。
再看一个满足第一条,不满足第二条的情况
structstu2
{
int k;
short t;
};
成员k的偏移量为0;成员t的偏移量为4,都不需要调整。
但计算出来的大小为6,显然不是成员k大小的整数倍。
因此,编译器会在成员t后面补上2个字节,使得结构体的大小变成8从而满足第二个要求。
由此可见,大家在定义结构体类型时需要考虑到字节对齐的情况,不同的顺序会影响到结构体的大小。
对比下面两种定义顺序
struct stu3 structstu4
{ {
char c1; char c1;
int i; char c2;
char c2; int i;
}
}
虽然结构体stu3和stu4中成员都一样,但sizeof(structstu3)的值为12而sizeof(structstu4)的值为8。
如果结构体中的成员又是另外一种结构体类型时应该怎么计算呢?
只需把其展开即可。
但有一点需要注意,展开后的结构体的第一个成员的偏移量应当是被展开的结构体中最大的成员的整数倍。
看下面的例子,
structtemp
{
short i; +1
struct
{
charc; +5
intj; +6
}ss; +10+2
intk; +4
}; =16
结构体temp的成员ss.c的偏移量应该是4,而不是2。
整个结构体大小应该是16。
注意在linux下时,整个结构体的大小应该是:
char对齐模数是1,short是2,int是4,float是4,double(linux是4,windows是8)
所以对于如下的结构体:
(32位机,默认设置)
struct temp
{
int i;
double j;
};
对于在WINDOWNS系统下,整个结构的大小应该是16,在LINUX系统下,整个结构的大小应该是12
当控制结构的成员封装到内存并为模块中的所有结构指定相同的封装时。
#pragmapack(n) 是把所有的成员的对齐模数都设置为n,比如设置为1后,就是一个一个的挨着存放,结构大小也就是成员大小之和了。
n必须小于默认的对齐模数,也就是说只能向小设,不能向大设