今天我们来学习一种全新的类型,结构体,相信大家对其或多或少都有所了解,今天就来系统讲解一下。
1.认识结构体
结构体是一个集合,让我们对比数组来看一下
数组是集合,但只能储存同样类型的数据,而结构体可以储存不同类型的数据
数组也可以是一种数据结构,存储时是连续存储的,而结构体也可以构成一种数据结构,就是链表
两者最大的区别就是数据是否是连续存储的,如图所示:
2.结构体的声明
struct str
{
member_list;
}variable_list;
以上就是创建了一个str类型的结构体,其中,str是这个结构体的名称,member_list表示成员变量,可以是不同类型的变量int,char,long,float都可以,variable_list表示多个结构体变量,表示用该结构体创建的结构体变量(不是必要的,可以在之后需要的时候创建)
3.结构体的内存对齐现象
进入该部分前,先来看这样一个问题
#include <stdio.h>
struct str1
{
char a;
char b;
int c;
};
struct str2
{
char a;
int c;
char b;
};
int main()
{
str1 s1;
str2 s2;
printf("%d\n",sizeof(s1));
printf("%d\n",sizeof(s2));
return 0;
}
大家觉得这两个结构体的大小打印出来是否是一样的?
肯定是不一样的,毕竟我都这么问了,结果打印出来是8和12
可是简单理解的话,成员的数量类型都一样,结果应该是一样的,都是6才对
说明了结构体在存储数据的时候应该是会发生内存的浪费的,那么浪费产生的原因是什么呢,就是数据的对齐
这里引入一个偏移量的概念,所谓偏移量就是指变量存储的地址相对于结构体地址的偏移大小,单位是字节,在c语言中,我们可以使用offsetof函数来得到结构体中不同类型储存时的偏移量
对齐规则
结构体的第一个变量要对齐到偏移量为0处,剩下的变量要对齐到某个数字的整数倍,这个数字就是对齐数,他是默认对齐数和变量大小的较小值,在vs编译器中默认对齐数是8,编译器不同默认对齐数可能不同,结构体的总大小为最大对齐数的整数倍
知道这一点我们来看刚刚的例子
对str2来说
第一个char数据放在第一个,int大小为4比8小,所以它的对齐数是4,那么到4的整数倍之前的空间就都会被浪费掉,最后一个char放入,至此占用了9个字节的空间,又因为结构体的大小要是最大对齐数(此题为4)的整数倍,所以大小是12,空的空间都是浪费的
为什么对齐
对齐就是使数据访问的时候更加方便,加入计算机可以一次性取出8个字节的数据进行处理,对其过后的数据就不容易在每次取数据时丢失可以减少时间上的损失
4.位段
位段是结构体的一种,位段空间需要1个或4个字节的方式来开辟
struct s
{
char a1:1;
char a2:2;
char a3:6;
};
冒号后面的数字代表这样一个类型占据几个比特位,如果开辟的空间用不完,剩下的比特位空间就会浪费掉
位段存在的意义就是对数据分配合适的大小,节省空间,但是会存在跨平台的问题
感兴趣的同学可以更加深入的了解位段的应用。
今天有关结构体的介绍就告一段落,希望有帮到你
封面:泡水灵梦,作者:c7肘