36深入理解C指针之---结构体的内存处理
一、有关结构体的内存处理包括,结构体指针和结构体成员指针的内存分配、结构体成员的数据对齐、结构体的内存释放
1、定义:与自定义数据类型(结构体)有关的内存分配、大小和释放问题
2、特征:
1)、用内存分配函数malloc()和释放free()和长度测试strlen()函数完成相关的内存操作工作;
2)、为不含有指针成员结构体分配内存时,与普通类型分配的方式是一样的;
3)、释放不含有指针成员结构体内存时,与普通内存释放也是一样的;
4)、为含有指针成员结构体分配内存时,必须先分配整个结构体的内存,再申请结构体指针成员的内存;
5)、释放含有指针成员结构体内存时,必须先释放所有结构体指针成员的内存,再释放结构体内存;
6)、结构体需要的内存大小和实际分配的大小可能会有所偏差;
7)、使用结构体指针访问是需要特别留心,尽量避免访问到结构体成员中的额外空白内存;
8)、释放不含有指针成员结构体内存时,与普通内存释放也是一样的;
9)、为含有指针成员结构体分配内存时,必须先分配整个结构体的内存,再申请结构体指针成员的内存;
10)、释放含有指针成员结构体内存时,必须先释放所有结构体指针成员的内存,再释放结构体内存;
3、结构体的内存分配应用:
1)、结构体指针需要手工分配内存
2)、结构体中还有指针成员需要手工分配内存
3)、必须先分配结构体内存,再分配成员内存
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdbool.h> 5 6 int main(int argc, char **argv) 7 { 8 typedef struct _student{ 9 char *name; 10 char *address; 11 int age; 12 short id; 13 bool sex; 14 } Student; 15 16 Student stu; 17 stu.name = (char *)malloc(strlen("zhangsan") + 1); 18 strcpy(stu.name, "zhangsan"); 19 stu.address = (char *)malloc(strlen("jiangxijiujiang") + 1); 20 strcpy(stu.name, "jiangxijiujiang"); 21 stu.age = 20; 22 stu.id = 1102; 23 stu.sex = true; 24 25 printf("stu inf: "); 26 printf("stu.name: %s\n", stu.name); 27 printf("stu.address: %s\n", stu.address); 28 printf("stu.age: %d\n", stu.age); 29 printf("stu.id: %d\n", stu.id); 30 printf("stu.sex: %d\n", stu.sex); 31 printf("\n"); 32 33 Student *ptrStu; 34 ptrStu = (Student *)malloc(sizeof(Student)); 35 ptrStu->name = (char *)malloc(strlen("lisi") + 1); 36 strcpy(ptrStu->name, "lisi"); 37 ptrStu->address = (char *)malloc(strlen("jiangxishangrao") + 1); 38 strcpy(ptrStu->address, "jiangxishangrao"); 39 ptrStu->age = 29; 40 ptrStu->id = 2109; 41 ptrStu->sex = false; 42 43 printf("ptrStu inf: "); 44 printf("ptrStu.name: %s\n", ptrStu->name); 45 printf("ptrStu.address: %s\n", ptrStu->address); 46 printf("ptrStu.age: %d\n", ptrStu->age); 47 printf("ptrStu.id: %d\n", ptrStu->id); 48 printf("ptrStu.sex: %d\n", ptrStu->sex); 49 printf("\n"); 50 free(ptrStu->name); 51 free(ptrStu->address); 52 free(ptrStu); 53 54 return 0; 55 }
代码说明:
1)、第7-14行定义结构体Student,结构体中有指针成员变量;
2)、第16行声明普通结构体变量stu;
3)、第17行为结构体变量stu的指针成员变量name申请内存空间,第19行为address申请内存空间;
4)、第18行为结构体变量stu的指针成员变量name复制内容,使用字符串复制操作实现,第20行为address复制内容;
5)、第33行声明指针结构体变量ptrStu;
6)、第34行为指针结构体变量ptrStu申请内存空间;
7)、第35行为结构体变量ptrStu的指针成员变量name申请内存空间,第37行为address申请内存空间;
8)、第36行为结构体变量ptrStu的指针成员变量name复制内容,使用字符串复制操作实现,第38行为address复制内容;
9)、结构体指针变量的成员访问符号,一般使用ptrStu->name,偶尔见到有人使用(*ptrStu).name,建议使用前者;
4、结构体的内存大小和对齐应用:
1)、结构体中成员变量的大小影响结构体的大小
2)、结构体中成员变量的类型影响结构体的大小
3)、结构体中成员变量的声明顺序影响结构体的大小
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdbool.h> 5 6 int main(int argc, char **argv) 7 { 8 typedef struct _student1{ 9 char *name; 10 char *address; 11 int age; 12 short id; 13 bool sex; 14 char se0; 15 } Student1; 16 17 typedef struct _student2{ 18 char *name; 19 char *address; 20 int age; 21 bool sex; 22 short id; 23 char se0; 24 } Student2; 25 26 typedef struct _student3{ 27 char se0; 28 char *name; 29 bool sex; 30 char *address; 31 int age; 32 short id; 33 } Student3; 34 35 Student1 *ptrStu1; 36 printf("Student1 size: %d\n", sizeof(Student1)); 37 printf("Student2 size: %d\n", sizeof(Student2)); 38 printf("Student3 size: %d\n", sizeof(Student3)); 39 40 return 0; 41 }
代码结果为:
Student1 size: 24 Student2 size: 32 Student3 size: 40
代码说明:
1)、Student1、Student2和Student3的成员类型及大小是完全一样;
2)、Student1、Student2和Student3的成员声明的顺序不完全一样;
3)、结构体大大小完全不一样;
4)、name指针大小为8个字节,同样address为8个字节,age大小为4个字节,id为2个字节,sex为1个字节,se0为1个字节;
5)、按照说明4完全成立,Student1和Student2和Student3大小应该都是24个字节;
6)、结构体中成员变量间存在着内存对齐,基本规则就是下个成员的大小决定上个成员的内存结束位置,至少是下个成员大小的整数倍,最终大小是4或8的倍数;
7)、结构体Student1中name:8, address : 8, age :4, id : 2, sex : 1, se0:1,共计24字节;
8)、结构体Student2中name:8, address : 8, age :4, sex : 1,id : 2, se0:1,共计32字节;
9)、结构体Student3中se0:1,name:8, sex : 1,address : 8, age :4, id : 2, 共计40字节;
5、结构体的内存释放应用:
1)、参加3的应用部分
6、结构体数组的应用:
1)、声明数组时,指定数据类型为结构体类型即可
7、位结构体的应用,主要应用于需要按位访问数据时,位结构更加方便与快捷:
1)、声明结构体时,与其他结构体的声明方式完全相同;
2)、结构体中的数据类型只能是unsigned或signed,当成员长度为1时,默认是unsigned;
3)、位结构的成员变量的顺序是位排列的顺序;
4)、位结构的成员变量不能是指针或数组类型;
5)、位结构的总长度是所有成员定义的位数之和,可以超过2个字节;
6)、位结构的使用方法与其他结构使用方式一样,也可以与其他结构一起使用;
7)、位结构变量可以是指针或数组变量