1.共用体:html
共用体是一种特殊的数据类型,容许您在相同的内存位置存储不一样的数据类型。您能够定义一个带有多成员的共用体,可是任什么时候候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。
数据结构
为了定义共用体,您必须使用 union 语句,方式与定义结构相似。ide
例子:spa
union Data { code
int i; htm
float f; 内存
char str[20]; ci
} data;字符串
这意味着一个变量(相同的内存位置)能够存储多个多种类型的数据。您能够根据须要在一个共用体内使用任何内置的或者用户自定义的数据类型。共用体的占用的内存大小由最大的变量决定---这个例子里面就是字符串(char str[20]),占用20个字节内存。get
为了访问共用体的成员,咱们使用成员访问运算符(.)。 可是和结构体不同,因为共用体本质上是一个内存位置,因此会致使在同一时间里只能有一个值占用内存位置。
好比:
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf("data.str : %s\n", data.str);
打印(printf)这个三个值,前两个值都会损坏,由于内存位置被赋给了str.
可是假如是:
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
printf( "data.str : %s\n", data.str);
每次内存被占用以后都打印了出来,而后又从新赋值,因此不会形成损坏。
共用体做用:
节省内存,有两个很长的数据结构,不会同时使用,好比一个表示老师,一个表示学生,若是要统计教师和学生的状况用结构体的话就有点浪费了!用共用体的话,只占用最长的那个数据结构所占用的空间,就足够了!
共用体应用场景:
通讯中的数据包会用到共用体:由于不知道对方会发一个什么包过来,用共用体的话就很简单了,定义几种格式的包,收到包以后就能够直接根据包的格式取出数据。
2.位域(深刻):
假设咱们须要一个结构体只储存一个固定长度的值(好比说 1,0 这种来表明true/false --- 0001只须要一个bit)的,若是正常去定义,须要两个 int (每一个4字节 Byte,一共 8 Byte)。C 语言提供了一种更好的利用内存空间的方式。若是您在结构内使用这样的变量,您能够定义变量的宽度来告诉编译器,您将只使用这些字节Byte。
定义例子:
struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status;
如上,status 变量将占用 4 个字节(byte)的内存空间,可是只有 2 位(bit)被用来存储值,意思就是说这两个成员共用了一个int的内存空间(都是同类型)。
若是您用了 32 个变量,每个变量宽度为 1 位,那么 status 结构将使用 4 个字节,但只要您再多用一个变量,若是使用了 33 个变量,那么它将分配内存的下一段来存储第 33 个变量,这个时候就开始使用 8 个字节。
Age.age = 7;
printf( "Age.age : %d\n", Age.age );
Age.age = 8; // 二进制表示为 1000 有四位,超出
printf( "Age.age : %d\n", Age.age );
output :
Age.age : 7 Age.age : 0
这个结果还会伴随着警告。
sub:(来自上章)
1.一个位域存储在同一个字节中,如一个字节所剩空间不够存放另外一位域时,则会从下一单元起存放该位域。也能够有意使某位域从下一单元开始。
2.因为位域不容许跨两个字节,所以位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。若是最大长度大于计算机的整数字长,一些编译器可能会容许域的内存重叠,另一些编译器可能会把大于一个域的部分存储在下一个字中。
3.位域能够是无名位域,这时它只用来做填充或调整位置。无名的位域是不能使用的.
4.位域在本质上就是一种结构类型,不过其成员是按二进位分配的。
5.结构体变量的首地址可以被其最宽基本类型成员的大小所整除。
6.结构体每一个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,若有须要编译器会在成员之间加上填充字节(internal adding)。即结构体成员的末地址减去结构体首地址(第一个结构体成员的首地址)获得的偏移量都要是对应成员大小的整数倍。
7.
超出范围并非直接丢弃,而是保留对应的 3 位的值。
好比 8 是 00001000,按照位域,对应 3 位的值是 000,因此打印结果是 0;
可是 9 是 00001001,按照位域,对应 3 位的值是 001,因此打印结果是 1;
同理 10 是 00001010,按照位域,对应 3 位的值是 010,因此打印结果是 2;
引用: