导言
结构体是C语言中的一种自定义类型,它的值(成员变量)可以是多个,且这些值可以为不同类型,这也是和数组的主要区别,下面将介绍它的一些基本用法,包括:结构体的创建、结构体变量的声明、初始化、结构体的访问、结构体的内存对齐等。
目录
结构体的创建
cpp
struct stu {//比如描述一个学生
char name[10];//名字
int age;//年龄
int score;// 得分
};
结构体变量的声明
常用的有以下3种:
1.在结构体创建时同时声明结构体变量:
cpp
struct stu {//比如描述一个学生
char name[10];//名字
int age;//年龄
int score;// 得分
}stu1,stu2;//声明了stu1和stu2
2.先创建结构体,后声明(包括在函数内部声明):
cpp
//2.先创建结构体,后初始化:
struct stu {//比如描述一个学生
char name[10];//名字
int age;//年龄
int score;// 得分
};
struct stu stu1, stu2;
3.使用typedef先重命名,再声明:
cpp
//3.使用typedef先重命名,再声明:
typedef struct stu {//比如描述一个学生
char name[10];//名字
int age;//年龄
int score;// 得分
}stu;//当前面使用typedef时,分号前不再是变量声明,而是重命名后的类型
stu stu1, stu2;//声明了stu1和stu2
关于typedef重命名结构体,也可先创建结构体,再重命名:
cpp
struct stu{
char name[10];//名字
int age;//年龄
int score;// 得分
};
typedef struct stu stu;
stu stu1, stu2;
结构体的特殊声明:匿名结构体:
结构体成员的初始化、访问
初始化:
按顺序初始化:
cpp
struct stu {//比如描述一个学生
char name[10];//名字
int age;//年龄
int score;// 得分
};
int main() {
struct stu stu1 = { "mariiy",18,89 };//按顺序初始化
return 0;
}
不按顺序初始化:
格式:.成员名=初始值
cpp
struct stu {//比如描述一个学生
char name[10];//名字
int age;//年龄
int score;// 得分
};
int main() {
struct stu stu1 = { .age=19,.name="joke",.score=90};//不按顺序初始化
return 0;
}
访问:
直接使用变量名(操作符".")
格式:变量名.成员名
使用指针(操作符"->")
格式:结构体指针->成员名
结构体的内存对齐
结构体的内存对齐描述了结构体成员在内存中的存储位置,是决定结构体内存大小的重要因素。
因为结构体内存对齐的因素存在,两个存储着同等数量、类型的结构体,会因为成员在结构体内部顺序的不同,导致占用内存大小的不同。
如:
这时结构体大小为16字节。
我们变换一下顺序(将score移到第二位)
这时结构体大小为20字节。
两个结构体内的成员类型、个数完全一样,只是声明顺序不一样,导致结构体大小不一样。
对齐规则:
●结构体的第一个成员对齐到偏移量为0结构体变量的起始地址处。
●其他成员要对齐到对齐数的整数倍数处(偏移量的整数倍)
对齐数:编译器默认的对齐数与成员类型大小的较小值(数组类型大小为成员类型大小)
---vs上默认对齐数是8
---Linux没有默认对齐数,对齐数就是成员类型大小
●结构体的总大小为最大对齐数(所有成员的对齐数中最大的那个)的最小整数倍
●如果嵌套了结构体,结构体成员会对起到它的最大对齐数(不会再与编译器的默认对齐数比较)的整数倍数处
所以我们可以分析在上面的两个结构体中内存布局:
内存布局:
内存布局: