• 12_C++_《结构体和文件》_笔记整理


    结构体

    基本内容

    结构体类型的定义

    定义结构体类型时不要直接给成员赋值
    结构体只是一个类型,编译器还没有为其分配空间
    只有根据其类型定义变量时,才分配空间,有空间后才能赋值

    结构体变量的定义

    struct Person{
    	char name[64];
    	int age;
    }p1; // 定义类型同时定义变量
    struct{
    	char name[64];
    	int age;
    }p2; // 定义类型同时定义变量,但是这是匿名的
    struct Person p3; //通过类型直接定义
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结构体变量的初始化

    struct Person{
    	char name[64];
    	int age;
    }p1 = {"john",10}; // 定义结构体类型同时初始化变量
    struct{
    	char name[64];
    	int age;
    }p2 = {"Obama",30}; // 定义结构体(匿名)类型同时初始化变量
    struct Person p3 = {"Edward",33}; // 通过类型直接定义
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结构体成员的使用

    在栈区上直接用点域访问成员变量,也可以取地址用箭头
    在堆区要先开辟一个结构体大小的空间,然后按照返回的指针用箭头访问成员变量,也可以解引用然后用点域的方式访问成员变量

    struct Person{
    	char name[64];
    	int age;
    };
    void test(){
    	//在栈上分配空间
    	struct Person p1;
    	strcpy(p1.name, "John");
    	p1.age = 30;
    	//如果是普通变量,通过点运算符操作结构体成员
    	printf("Name:%s Age:%d\n", p1.name, p1.age);
    	//在堆上分配空间
    	struct Person* p2 = (struct Person*)malloc(sizeof(struct Person));
    	strcpy(p2->name, "Obama");
    	p2->age = 33;
    	//如果是指针变量,通过->操作结构体成员
    	printf("Name:%s Age:%d\n", p2->name, p2->age);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    7.1.5 结构体赋值

    相同的两个结构体变量可以相互赋值
    把一个结构体变量的值拷贝给另一个结构体,这两个变量还是两个独立的变量

    深拷贝和浅拷贝

    浅拷贝 → \rightarrow 逐字节拷贝
    如果属性中有指向堆区的内容,在释放期间会导致堆区重复释放,并且还有内存泄露
    解决方案:利用深拷贝 → \rightarrow 手动赋值

    // 一个老师有N个学生
    typedef struct _TEACHER{
    	char* name;
    }Teacher;
    void test(){
    	Teacher t1;
    	t1.name = malloc(64);
    	strcpy(t1.name , "John");
    	Teacher t2;
    	t2 = t1;
    
    	// 对手动开辟的内存,需要手动拷贝,也就是深拷贝
    	t2.name = malloc(64);
    	strcpy(t2.name, t1.name);
    
    	// 再次释放后就不会报错了
    	if (t1.name != NULL){
    		free(t1.name);
    		t1.name = NULL;
    	}
    	if (t2.name != NULL){
    		free(t2.name);
    		t1.name = NULL;
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    嵌套指针

    1. 设计结构体 → \rightarrow struct Person { char * name,int age }
    2. 在堆区创建 → \rightarrow 结构体指针数组 → \rightarrow malloc(sizeof(struct Person *) * 3);
    3. 给每个结构体也分配到堆区;给每个结构体的姓名分配到堆区
    4. 打印数组中所有人的信息
    5. 释放堆区数据

    成员偏移量

    可以利用offsetof来计算结构体中属性的偏移;
    也可以通过地址的相加运算,计算偏移量;

    // 一旦结构体定义下来,则结构体中的成员内存布局就定下了
    #include 
    struct Teacher
    {
    	char a;
    	int b;
    };
    void test01(){
    	struct Teacher  t1;
    	struct Teacher*p = &t1;
    	int offsize1 = (int)&(p->b) - (int)p;  // 成员b 相对于结构体 Teacher的偏移量
    	int offsize2 = offsetof(struct Teacher, b);
    	printf("offsize1:%d \n", offsize1); // 打印b属性对于首地址的偏移量
    	printf("offsize2:%d \n", offsize2);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    字节对齐

    1. 内存对齐原因:以空间换时间,避免二次访问
    2. 对于自定义数据类型对齐规则:
      (1)从第一个属性开始 ,偏移为0 ;
      (2)第二个属性开始,地址要放在该类型的大小整数对齐模数比小的值的整数倍
      (3)所有的属性都计算结束后,整体再做二次对齐整体需要放在属性中最大类型对齐模数比小的值的整数倍
      (4)如果查看对齐模数#pragma pack(show) 默认对齐模数是8,可以将对齐模数改为 2的n次方
    3. 当结构体嵌套结构体时候,只需要看子结构体中最大数据类型就可以了

    文件读写

    基本知识

    随机位置读写
    → \rightarrow fseek (文件指针,偏移, 起始位置 (SEEK_SET/SEEK_END/SEEK_CUR) )
    → \rightarrow rewind(文件指针)将文件光标置首
    → \rightarrow perror打印宏的提示错误信息,其中error宏是全局变量

    注意事项

    1. 当按照字符的方式读文件时候,通常利用判断EOF获取是否读到文件尾
    2. 当对自定义数据类型写入文件时,不要将指针写入到文件里,要将指针指向的内容写入
  • 相关阅读:
    Ubuntu下查看资源占用情况
    如何挑选自媒体平台进行创作?这3个关键需要把握
    炮轰特斯拉「无图」,一家老牌图商的反击
    大数据Kudu(一):什么是Kudu
    ros下配置机器人系统V1
    【开题报告】基于SSM的化工企业安全培训考试系统的设计与实现
    从0到1学SpringCloud——13 gateway RouteLocator配置路由规则
    java毕业设计本地助农产品销售系统mybatis+源码+调试部署+系统+数据库+lw
    FFmpeg直播能力更新计划与新版本发布
    openssl 之 RSA加密数据设置OAEP SHA256填充方式
  • 原文地址:https://blog.csdn.net/m0_48948682/article/details/126072061