目录
自定义类型分为三种:结构体类型,枚举类型,联合体类型。
结构体类型
结构体声明
struct student//struct student 表示结构体类型名
{
char name[20];//结构体成员
int age;
int scores;
}s1;//s1表示定义的结构体变量
特殊的声明:
struct
{
char name[20];
int age;
}s;//没有定义类型名,这种结构体称为匿名结构体
结构体变量的定义和初始化
结构体只能在定义的时候进行初始化,后面只能对成员单独修改。
struct student //struct student 表示结构体类型名
{
char name[20];
int age;
int scores;
}s1={"a",18,90};//s1表示定义的结构体变量,分号不能丢!
int main()
{
struct student s2 = { "b",12,80 };
//结构体只能在定义的时候进行整体初始化!
//后面只能对结构体成员单独修改
//s2 ={ "a",55,66 };->这是错误的
printf("%s %d %d\n", s2.name, s2.age, s2.scores);
s2.age = 20;
s2.scores = 100;
printf("%s %d %d\n", s2.name, s2.age, s2.scores);
return 0;
}
结构体内存大小
struct student
{
char name[20];
char sex[5];
int age;
};
int main()
{
struct student s = { "qq","nan",50};
printf("%d", (int)sizeof(struct student));
return 0;
}
猜猜大小是多少呢?是29吗? 错错错!是32,为什么呢?
这里就要讲到结构体内存对齐了。
结构体内存对齐
结构体内存对齐规则:
1.第一个成员在结构体偏移量为0处。
2.其他成员要对齐到偏移量为对齐数的整数倍地址。
对齐数:编译器默认的对齐数大小与该成员大小的较小值。vs默认对齐数为8。
3.结构体总大小为结构体最大对齐数的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
下面详细讲解:
struct S1
{
char c1;
int i;
char c2;
};
结构体内存对齐的优点
1.可移植性高,某些平台不能访问任意位置。
2.读取速度快,内存不对齐,可能要访问多次。
位段
1.位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型。
2.位段空间是按照4或1个字节开辟,取决于成员类型。
3.位段可移植性差。
//位段
struct S
{
char a : 3;//3个bit位
char b : 4;//4个比特位
char c : 5;
char d : 4;
};
int main()
{
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
}
想想看,这里的位段结构体占多少字节呢?
枚举类型
枚举类型定义
枚举类型第一个成员默认为0,依次往后递增。
enum Day//星期
{
Mon, //0
Tues,//1
Wed,//2
Thur,//3
Fri,//4
Sat,//5
Sun//6
};
当然,我们可以更改枚举成员的值。
我们可以发现,赋值前面没有改变,后面随着赋值改变。
枚举优点
1. 增加代码的可读性和可维护性。
2. 和#define定义的标识符比较枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)。
4. 便于调试。
5. 使用方便,一次可以定义多个常量。
联合体
union Un
{
char c;
int i;
};
联合体共用一块空间,所以其内存大小至少为其最大成员大小。
联合体也要内存对齐!
当对c进行更改后,i的值也要随之改变,因为共用一块空间。
以上就是全部内容了,希望对你有所帮助。