目录
一:结构体类型
定义变量
结构体类型能将不同类型结合在一起形成一个新的类型,这样便于我们使用数据
struct stu
{
int i;
char n;
};
int main()
{
return 0;
}
struct stu就成为了一个新的类型名,我们当然也可以用它来定义变量
struct stu
{
int i;
char n;
}s; //在结构体类型下直接定义的,s就是一个全局的结构体变量
int main()
{
struct stu k; //k是一个局部的结构体变量
return 0;
}
变量初始化
在创建变量的时候我们可以像其他变量一样用=对里面的数据进行初始化
struct stu
{
int i; //int i=1;
char n; //char n='1'; 这样是错误的初始化方法,编译器也会报错
}s = {1,'1'};
int main()
{
struct stu k = { 1,'1' };
return 0;
}
变量的使用
一:使用.操作符进行访问数据
struct stu
{
int i;
char n;
};
int main()
{
struct stu k = { 1,'1' };
printf("%d", k.i); //使用.操作符
printf("%c", k.n);
return 0;
}
二:使用结构体类型指针
struct stu
{
int i;
char n;
};
int main()
{
struct stu k = { 1,'1' };
struct stu* p = &k; //定义一个结构体类型指针p;
printf("%d", (*p).i); //方法一:先对p解引用找到k,再使用.操作符
printf("%d", p->i); //方法二:使用->操作符直接进行访问
return 0;
}
结构体大小计算
结构体的大小不仅和结构体里面类型和数量有关,也和排列顺序有关
结构体对齐数
C语言的结构体有内存对齐的规则,而内存对齐是需要参照对齐数的,VS中默认对齐数为8
计算结构体大小有几个规则
一:类型大小若比默认对齐数小,且是默认对齐数的倍数的话,就能使用自身类型大小做为对齐数
二:第一个成员在与结构体变量偏移量为0地址处,其他成员变量要对齐到对齐数的整数倍
三:结构体总大小为最大对齐数的整数倍(每个成员变量都有一个对齐数)
为什么存在内存对齐呢
为了访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存仅需一次访问
总的来说:就是牺牲内存来换取访问速度
位段
位段算是结构体的一种特殊实现
位段的声明和结构是类似的,有两个不同:
1:位段的成员必须是int,unsigned int ,sighed int ,char等(4字节以内的整形家族)
2:位段的成员名后边有一个冒号和数字
如:
struct s
{
char a : 2;
char b : 3;
char c : 5;
};
图中的意思是给a分配2个比特位,b分配3个比特位,c分配5个比特位(因为char类型大小为1字节,所以分配比特位时大小要小于8比特位)
所以位段的作用是让我们更合理的分配和使用内存
二:枚举
枚举的定义
枚举中的成员是常量,也称枚举常量
enum en
{
MALE,
FEMALE
};
上面是枚举类型的定义,
MALE的默认值为0,向下递增加一,FEMALE的值则为1
enum en
{
MALE=2,
FEMALE
};
设MALE的值为2,则FEMALE的值为3
也可以根据自己的需要修改大小
枚举的使用
枚举中定义的成员是可以直接使用的,如:
enum en
{
MALE=2,
FEMALE
};
int main()
{
int a[MALE];
return 0;
}
因为枚举中的成员是常量,所以可以直接来定义数组
也可以定义一个枚举类型的变量
enum en
{
MALE=2,
FEMALE
};
int main()
{
enum en a = MALE; //a是变量,值为2
return 0;
}
三:联合体
联合体的定义
union un
{
char a;
int b;
};
int main()
{
union un u;
return 0;
}
图上定义了一个u变量,使用方法也和结构体类似,使用.操作符和->进行访问
联合体大小
联合体的大小与成员中大小最大的相等,同时也需要是最大对齐数的整数倍
如图:
联合体中的成员是共用同一块空间的
所以联合体类型变量在使用时一次只能使用一种类型