目录
结构体
结构体类型的定义形式
结构体类型的大小
内存计算例子
共用体union
用共用体判断大小端
结构体和共用体对比
qsort()
结构体
结构体类型——用来描述复杂数据的一种数据类型
构造类型(用户自定义类型)
struct 结构体类型名
{
成员列表;
};
struct关键字:表明是在构造一个结构体的类型
结构体名:用来描述结构体这个类型的一个名称
成员列表:表示要描述的复杂数据中用到的具体的成员变量
定义的方式与之前变量的方式相同
多个成员变量之间用分号隔开
最后有一个分号表示结束
struct student
{char name[30]; int sno;float score;char sex;
};//表示定义出一个数据类型
有数据类型,可以:定义变量、指针变量、数组
结构体使用方法
自己构造出这个结构体类型
有了类型——定义变量、数组、指针
结构体类型的指针——做函数形参、做函数返回值
- 结构体类型的使用过程
先定义出类型
定义变量
- 定义变量
struct 结构体名 变量名;
- 结构体初始化
struct student s = {};
看每个成员变量具体是什么数据类型
根据每个成员变量自身的数据类型进行初始化
初始化顺序:按照定义的顺序,依次初始化
struct student s = {666,"jack",1,90.4};
- 结构体变量的引用
结构体数据引用时一般是引用到具体的数据
运算符 . (结构体成员运算符)
结构体变量名.成员变量名(访问某个结构体的成员)
s.sno引用s中的sno
结构体类型的数组
struct student s[3];
-> 指向结构体成员运算符
结构体指针->成员名
结构体类型的定义形式
形式1:先定义类型,然后定义变量
struct demo
{};
struct demo d;
形式2:定义类型的同时定义变量
struct demo
{
} d;
形式3:定义类型的同时定义变量,可以省略结构体名
(结构体类型只用一次)
struct
{
} d;
结构体类型的大小
内存对齐
结构体的对齐规则:内存地址的对齐
1.在32位的平台上,默认都是按4字节对齐的
2.对于成员变量各自在自己的自然边界上对齐
char——1字节
short ——2字节
int——4字节
3.如果:成员变量中有比4字节大,
此时整个结构体 按照4字节对齐。
4.如果:成员变量中没有有比4字节大。此时 整个结构体 按照最大的那个成员对齐
32位的平台
如果有超过4字节,按照4字节对齐。如果没有超过4字节的,则按成员变量中最大对齐64位的平台
如果有超过4字节,按照超过的最大的成员对齐。如果没有超过4字节的,则按成员变量中最大对齐
同类型的结构体变量之间可以相互赋值
struct student s1;
struct student s2;
s2 = s1;
结构体类型的大小计算
内存对齐是指将数据存储在特定的地址上,以便硬件能够更高效地访问这些数据。不同的数据类型(例如
int
、char
、float
等)通常有不同的对齐要求,这些要求通常与数据类型的大小相关。例如:
char
类型的数据通常要求对齐到1字节的边界。int
类型的数据通常要求对齐到4字节的边界。double
类型的数据通常要求对齐到8字节的边界。内存对齐规则
基础对齐原则:结构体中的每个成员都必须按照其数据类型的对齐要求对齐。比如,如果一个结构体包含一个
int
,那么这个int
成员必须出现在一个4字节对齐的地址上。结构体对齐规则:结构体的总大小必须是其最大成员对齐要求的整数倍。例如,如果一个结构体中最大的成员是
double
(8字节对齐),那么结构体的总大小也必须是8的倍数,即使可能会存在一些“填充字节”(padding bytes)。
为什么要内存对齐(提高效率)
内存对齐的主要目的是提高访问内存的效率。在现代计算机中,CPU通常是按块(比如4字节或8字节)从内存中读取数据的。如果数据是对齐的,CPU可以一次性读取整块数据,这样效率更高。
如果数据未对齐,CPU可能需要进行多次内存访问才能读取完整的数据,或者需要进行额外的计算来调整地址,这会导致性能下降。
内存计算例子
在这个结构体 demo1
中,有一个整数成员 int i
和一个匿名 union
,该 union
包含以下三个成员:
char s[7]
:一个长度为7的字符数组,占用7个字节。int v
:一个整数,占用4个字节。float f
:一个浮点数,占用4个字节。
结构体的内存计算
-
匿名
union
的大小:union
的大小由其最大的成员决定。char s[7]
占用7个字节。int v
占用4个字节。float f
占用4个字节。 因此,union
的大小为7字节(char s[7]
是最大的成员)。
-
结构体的对齐要求:
int i
需要4字节对齐。union
的最大成员char s[7]
,虽然它本身是7个字节,但由于int v
和float f
可能会让整个结构体具有更严格的对齐要求,假设int
和float
都需要4字节对齐,整个union
的大小可能会被填充到8个字节。
-
计算总大小:
int i
占用4字节。union
占用8字节(对齐到4字节的倍数)。- 因此,整个结构体
demo1
的大小为4(int i
) + 8(union
) = 12字节。
共用体union
语法
union 共用体名
{
成员变量;
};
union demo
{
char a;
short b;
int c;
};
共用体:共用一块内存空间(最大成员的空间)
共用体初始化时只能给一个值,且默认给到第一个成员
共用体变量中的值,取决于最后一次给的值,还要看能影响几个值
用共用体判断大小端
在这个代码片段中,union
中有两个成员:
int a
:通常占用4个字节char b
:占用1个字节
由于 union
中所有成员共享同一块内存,因此 union
的大小由其最大的成员决定。在这个例子中,int a
是 union
中最大的成员,占用4个字节。因此,这个 union
的大小是 4字节
isLittleEndian
函数
- 该函数用于检查系统的字节序(大端或小端)
union
初始化时,将int a
设为1
(假设int
为4字节,即0x00000001
)- 然后,通过
char b
访问union
的第一个字节:
- 如果系统是小端序(little-endian),
char b
将读取0x01
,函数返回1
- 如果系统是大端序(big-endian),
char b
将读取0x00
,函数返回0
结构体和共用体对比
结构体中各个成员拥有自己独立的空间
共用体成员共用一块内存空间
qsort()
qsort()功能:排序数组
void qsort(void *base,//要排序的数组的首地址
size_t nmemb,//数组元素的个数
size_t size,//单个元素的大小
int (*compar)(const void *, const void *));//比较函数——提供比较依据
int compar(const void *a, const void *b)
{//比较函数——a、b代表要比较的数组元素
}