定义了union类型之后,data里面的内容都是占用的同一个内存空间。
所以12行后,给a赋值之后,b其实就不起作用了。
共用体占用的内存是所有元素当中占用最长的那个的内存。
共用体几个成员的地址都是一样的。
结构体的占用内存,不是单纯地将元素的内存大小进行累加(计算机将其内存重新规划了一下,提高了运行效率,用空间换时间)。
首先判断所有元素的偏移地址(相对结构体第一个内存地址的偏移量),a是0,b是4(a的内存字节数),c是5(a和b相加)。之后看一下每个元素的偏移地址,是不是他们自身占用的字节数的整数倍,比如c的偏移量是5个字节,占用了4个字节,这个时候在c的前面加上3个字节的内存补空,让c的偏移量变成8个字节,是4个字节的两倍。
之后,还要判断结构体总体的内存,是不是最大元素所占内存的整数倍,如果不是就在结构体最后补充字节数,直到满足要求。
%lu表示长整型,sizeof()用于输出内存大小。
%p表示地址,后面接&xxx输出内存地址。
union让不同类型的变量共用同一个内存单元,能节省内存空间,但只能存储一个成员;
声明方法:
union [name]{
...
};
使用:union [union_name] [value_name];
共用体声明时只能有一个常量。给共用体成员赋值时后赋值的变量值会覆盖前一个。
共用体所占的内存地址是其成员中内存地址最大的成员的内存地址。
结构体对象大小=最后一个成员的大小+最后一个成员的偏移量+填充字节数
偏移量:结构体中一个成员相对于结构体的首字节(即第一个成员的首字节)所距离的大小。(那么第一个成员相对于结构体的偏移量为0)
每个成员所占内存大小的偏移量=成员字节大小的整数倍。(若不是,则编译器会在前一个成员后做字节填充,使这个成员的偏移量=字节大小的整数倍。计算结构体内存地址大小时若总大小不等于最大成员字节大小的整数倍,会在最后一个成员后做字节填充。)
打印结构体的字节数:
printf("%lu",sizeof(...));
共用体元素地址都相同,可用:printf("%p\n",&data_1.a);
共用体为不同的变量提供一块内存
共用体:
1、不同数据类型的变量共享一个内存地址
2、该结构体所占实际内存为最大的成员所占
3、关键字union
union data{
..
..
}
union data data_1
struct 占用空间计算
共用体:
为不同变量提供同一块内存地址
声明方法:
union [name]{
...
};
使用:union [union_name] [value_name];
共用体声明时只能有一个常量。给共用体成员赋值时后赋值的变量值会覆盖前一个。
共用体所占的内存地址是其成员中内存地址最大的成员的内存地址。
结构体对象大小=最后一个成员的大小+最后一个成员的偏移量+填充字节数
偏移量:结构体中一个成员相对于共用体的首字节(即第一个成员的首字节)所距离的大小。(那么第一个成员相对于结构体的偏移量为0)
每个成员所占内存大小的偏移量=成员字节大小的整数倍。(若不是,则编译器会在前一个成员后做字节填充,使这个成员的偏移量=字节大小的整数倍。计算结构体内存地址大小时若最后一个成员的偏移量仍不等于这个成员字节大小的整数倍,会在最后一个成员后做字节填充。)
打印某个变量的字节大小:
printf("%lu",sizeof(...));
共用体与结构体其他基本相同
union的作用是让不同的类型的变量共享同一个内存地址
4-1 Linux C 公用体
abc 存放到一个公用体中,节省开销 ,同一时刻只能存储一个成员
union data{ int a;int b;int c;};
结构体空间大小涉及到字节对齐,对齐的目的是让计算机快速读写
结构体对象大小=最后一个成员的大小+最后一个成员的偏移量+填充字节数
每个成员所占内存大小的偏移量=成员字节大小的整数倍。
a的偏移量是0,b的偏移量是4,c的偏移量是8
结构体总大小是12,是最宽的基本类型成员大小(int ,4)的整数倍
公用体变量和各个成员的变量是一个地址
结构体占用的内存空间是字节对齐的,使计算机可以快速读写以空间换取时间:最后一个成员的偏移量+最后一个成员的大小+末尾的填充字节数
偏移量是此成员实际首地址和结构体首地址之间的距离;
成员字节大小,例,int是4字节, char是1字节
填充字节数偏移量不足4的倍数的,填充。
与结构体不同,共用体和其成员的地址都是一样的。
共用体 联合体 几个不同的类型变量使用同一个内存地址,节省一定的开销,同一时刻只能存储一个成员
union data{
int a;
char b;
int c;
}
union data data_1;
data_1.b='c';
data_1.a=10;//起作用
union data data_2={10};
共用体所占的内存长度是它所有成员里所占内存最长的成员长度
int为4,char为1,union长度为4
结构体(字节对齐,快速读写,空间换取时间)所占内存长度是最后一个成员的偏移量加上最后一个成员的大小加上末尾的填充字节数
偏移量是某一个成员的实际地址和结构体首地址之间的距离
a偏移量为0,b偏移量为a的大小4
每个成员相对于结构体首地址的偏移量是当前成员所占内存大小的整数倍,如果不是则填充字节
c偏移量为a的大小4+b的大小1等于5不能整除c的大小4,所以在b后填充字节使c的偏移量为8
结构体大小为8+4=12
结构体总大小是不是结构体中内存长度最长的成员长度的整数倍,如果不是填充字节
12可以整除4,如果不能整除则在c后填充字节
%lu sizeof(struct data)
共用体变量的地址和成员的地址是同一个
%p &data_1.a
共用体:共用体内的各元素分时占同一个地址上。
共用体内的数据存储的地址都是同一地址,每一时刻只能存储一个数据。共用体的存储地址长度是内部定义的最长数据类型的长度。而结构体的存储地址长度是内部各数据的长度的累加(注意:每个数据的偏移量必须是自身长度的整数倍,如果不是整数倍,则填充。如int,char,int,则最后的int的偏移量是int+char=5,则int前需要填充3个字节到8个字节,才为int的整数倍。如果总长度不是内部长度最大的整数倍,则最后一个的长度要填充)
共用体成员的地址是相同的
union data{} printf("%p\n%p\n%p\n",&data_1.a,&data_1.b,&data_1.c);
共用体:让几个不同类型的变量共享一个地址即内存单元,节省空间,缺点是同一时刻只能存储一个变量成员;
union data{ int a; int b; char c; float d; }; //声明一个共用体变量data; 初始化: union data data_1; data_1.a=10; data_b='Q';//现在真正起作用的是后一个被赋值的成员,即data_b; 也可以union data data_1={'Q'};//这里只能有'Q'一个常量; 共用体的内存长度是其最长成员的长度;
公用体:不同的变量使用相同的内存单元,可以节省开销,但同一时刻只能存储一个成员,只能有一个常量,内存长度是所有成员中最长的长度。
定义:union 名称{
成员类型 成员名;
成员类型 成员名;
.....
};
声明:union 名称 变量名;
赋值:名称.成员名=..;
结构体空间大小:最后一个成员的偏移量(成员的实际地址与结构体首地址之间的差距)+最后一个成员的大小+末尾的填充字节数(由于每个成员相对于结构体首地址的偏移量都得是当前成员所占内存大小的整数倍,若不是,则会加上填充字节 )
共用体