• 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
    ", stu.name);
    27     printf("stu.address: %s
    ", stu.address);
    28     printf("stu.age: %d
    ", stu.age);
    29     printf("stu.id: %d
    ", stu.id);
    30     printf("stu.sex: %d
    ", stu.sex);
    31     printf("
    ");
    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
    ", ptrStu->name);
    45     printf("ptrStu.address: %s
    ", ptrStu->address);
    46     printf("ptrStu.age: %d
    ", ptrStu->age);
    47     printf("ptrStu.id: %d
    ", ptrStu->id);
    48     printf("ptrStu.sex: %d
    ", ptrStu->sex);
    49     printf("
    ");
    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
    ", sizeof(Student1));
    37     printf("Student2 size: %d
    ", sizeof(Student2));
    38     printf("Student3 size: %d
    ", 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)、位结构变量可以是指针或数组变量

  • 相关阅读:
    PowerCat DNS 隧道通信
    各种反弹shell方法总结备忘
    Halo-个人独立博客系统
    内网渗透之域渗透
    使用 EW 作Socks5代理内网穿透
    PowerShell攻击:nishang
    贝叶斯网络
    Anaconda的CondaHTTPError问题
    完美解决win10系统无法安装.NET Framework问题
    敏捷开发中如何做质量管理?
  • 原文地址:https://www.cnblogs.com/guochaoxxl/p/6960854.html
Copyright © 2020-2023  润新知