【c语言指针详解】复杂数据结构的指针用法

目录

一、动态内存分配

1.1 使用malloc和free函数进行内存的动态分配和释放

1.2 内存泄漏和野指针的概念和解决方法

二、复杂数据结构的指针用法

2.1 结构体指针和成员访问操作符

2.2 指针数组和指向指针的指针

2.2.1 指针数组

2.2.2 指向指针的指针

2.3 动态内存分配与结构体指针的结合使用


🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。

🎁欢迎大家给我点赞👍、收藏⭐️,并在留言区📝与我互动,这些都是我前进的动力!

🌟我的格言:森林草木都有自己认为对的角度🌟。

一、动态内存分配

1.1 使用malloc和free函数进行内存的动态分配和释放

malloc 函数用于在运行时动态分配内存。它接受一个参数,表示需要分配的内存大小(以字节为单位),并返回一个指向分配内存的指针。如果分配成功,则返回的指针指向一块连续的、未初始化的内存区域;如果分配失败,则返回一个特殊的空指针(NULL)。

free 函数用于释放之前通过 malloc 或者类似函数动态分配的内存。它接受一个参数,表示需要释放的内存区域的起始地址。调用 free 函数将释放指定内存区域,这样释放的内存可以被重新分配给其他部分。

示例代码:

#include <stdio.h>
#include <stdlib.h>int main() {int* ptr;// 动态分配内存ptr = (int*)malloc(5 * sizeof(int));if (ptr == NULL) {printf("内存分配失败\n");exit(1); // 终止程序}// 使用分配的内存for (int i = 0; i < 5; i++) {ptr[i] = i + 1;}// 打印数组的值for (int i = 0; i < 5; i++) {printf("%d ", ptr[i]);}printf("\n");// 释放内存free(ptr);return 0;
}

输出结果如下:

上面的代码首先使用 malloc 函数动态分配了一个数组,然后使用循环给数组赋值。最后打印数组的值,并使用 free 函数释放了之前分配的内存空间。

1.2 内存泄漏和野指针的概念和解决方法

内存泄漏指的是分配的内存空间在不再使用时没有被释放,导致该内存无法被重新分配使用,并且随着程序运行时间的增长,已分配但未释放的内存会不断增加,最终导致程序崩溃。

可以使用 malloc 和 free 函数进行内存管理,为避免内存泄漏,释放内存的方法是在不再需要内存时调用 free 函数将其释放。

野指针则是指指向已释放或未分配内存空间的指针。

野指针的出现通常是由于对已释放的内存空间进行操作,或者未初始化指针的值导致指针指向未知的内存空间。使用野指针可能导致程序崩溃或者产生不可预测的结果。为避免野指针,应该在使用指针之前对其进行初始化,并在释放内存之后将指针置为 NULL

示例代码:

#include <stdio.h>
#include <stdlib.h>int main() {// 内存泄漏int* ptr = (int*)malloc(sizeof(int));if (ptr != NULL) {*ptr = 10;}// 需要释放内存free(ptr);// 野指针int* ptr2 = NULL;ptr2 = (int*) malloc( sizeof(int) );if ( ptr2 != NULL ) {*ptr2 = 20;// 在释放完内存后,应该将指针赋值为 NULL,避免出现野指针问题free(ptr2);ptr2 = NULL;}return 0;
}

二、复杂数据结构的指针用法

2.1 结构体指针和成员访问操作符

在 C 语言中,结构体是一种自定义数据类型,可以将不同类型的数据组合在一起,形成一个整体的数据类型。

结构体指针可以指向结构体变量,也可以指向动态分配的结构体内存空间,使用结构体指针可以方便地对结构体成员进行操作。

成员访问操作符有两种,一种是点操作符号 .,另一种是箭头操作符号 -> 。点操作符号用于访问结构体变量的成员,箭头操作符号则用于访问结构体指针指向的结构体变量的成员。

示例代码:

#include <stdio.h>
#include <string.h>// 定义一个结构体类型
struct Student {char name[20];int age;float score;
};int main() {// 定义一个结构体变量struct Student stu1 = {"Tom", 18, 90.5};// 定义一个结构体指针,指向结构体变量struct Student *p = &stu1;// 使用成员访问操作符号点操作符访问结构体变量的成员printf("%s %d %.2f\n", stu1.name, stu1.age, stu1.score);// 使用成员访问操作符号箭头操作符访问结构体指针指向的结构体变量的成员printf("%s %d %.2f\n", p->name, p->age, p->score);// 修改结构体指针指向的结构体变量的成员strcpy(p->name, "Jim");p->age = 19;p->score = 88.5;// 使用成员访问操作符号点操作符访问结构体变量的成员printf("%s %d %.2f\n", stu1.name, stu1.age, stu1.score);// 使用成员访问操作符号箭头操作符访问结构体指针指向的结构体变量的成员printf("%s %d %.2f\n", p->name, p->age, p->score);return 0;
}

输出结果如下:

在上面的代码中,我们首先定义了一个结构体类型 Student,然后定义了一个 Student 类型的结构体变量 stu1 和一个指向 stu1 的结构体指针 p。接着,我们使用点操作符号和箭头操作符号分别访问了结构体变量和结构体指针指向的结构体变量的成员,并修改了结构体指针指向的结构体变量的成员。

2.2 指针数组和指向指针的指针

2.2.1 指针数组

指针数组是一个数组,其元素都是指针类型。每个指针指向一个特定类型的对象或单元。可以通过索引来访问数组中的每个指针,并使用指针进一步操作对应的对象或单元。

示例代码:

#include <stdio.h>int main() {int num1 = 10, num2 = 20, num3 = 30;int* ptrArr[3];  // 声明一个指针数组ptrArr[0] = &num1;  // 指针数组的第一个元素指向 num1ptrArr[1] = &num2;  // 指针数组的第二个元素指向 num2ptrArr[2] = &num3;  // 指针数组的第三个元素指向 num3for (int i = 0; i < 3; i++) {printf("Element %d: %d\n", i, *(ptrArr[i]));}return 0;
}

输出结果如下:

在上述示例中,我们定义了一个指针数组 ptrArr,它有 3 个元素,每个元素都是 int 类型的指针。我们将 num1num2 和 num3 的地址依次赋给指针数组的元素,然后通过指针数组访问并打印对应的值。

2.2.2 指向指针的指针

指向指针的指针是一个指针,它存储了指针的地址。通过指向指针的指针可以间接地访问并修改指针所指向的变量。

示例代码:

#include <stdio.h>int main() {int num = 10;int* ptr = &num;int** ptrPtr = &ptr;  // 声明一个指向指针的指针printf("Value of num: %d\n", num);printf("Value of *ptr: %d\n", *ptr);printf("Value of **ptrPtr: %d\n", **ptrPtr);return 0;
}

输出结果如下:

在上述示例中,我们定义了一个指针 ptr,它存储了 num 的地址。然后,我们定义了一个指向指针的指针 ptrPtr,它存储了 ptr 的地址。通过 **ptrPtr,我们可以间接地访问并输出 num 的值。

2.3 动态内存分配与结构体指针的结合使用

可以使用动态内存分配和结构体指针的结合使用,来动态创建和操作结构体对象。这种组合可以在运行时动态地分配内存空间以存储结构体对象,并使用结构体指针来访问和操作这些对象。

示例代码:

#include <stdio.h>
#include <stdlib.h>typedef struct {int id;char name[20];
} Student;int main() {int numStudents;printf("Enter the number of students: ");scanf("%d", &numStudents);// 动态分配内存以存储指定数量的结构体对象Student* students = (Student*)malloc(numStudents * sizeof(Student));// 输入每个学生的信息for (int i = 0; i < numStudents; i++) {printf("Enter information for student %d:\n", i + 1);printf("ID: ");scanf("%d", &(students[i].id));printf("Name: ");scanf("%s", students[i].name);}// 输出每个学生的信息printf("\nStudent Information:\n");for (int i = 0; i < numStudents; i++) {printf("ID: %d, Name: %s\n", students[i].id, students[i].name);}// 释放动态分配的内存free(students);return 0;
}

在上述示例中,我们首先通过 malloc 函数动态分配了足够的内存空间来存储指定数量的 Student 结构体对象。然后,我们使用结构体指针 students 来访问和操作每个结构体对象的成员。通过输入每个学生的信息并输出学生信息,展示了动态分配内存和结构体指针的结合使用的一个简单例子。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/213558.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Learning Memory-guided Normality for Anomaly Detection 论文阅读

Learning Memory-guided Normality for Anomaly Detection 摘要1.介绍2.相关工作3.方法3.1网络架构3.1.1 Encoder and decoder3.1.2 Memory 3.2. Training loss3.3. Abnormality score 4.实验5.总结总结&代码复现&#xff1a; 文章信息&#xff1a; 发表于&#xff1a;cvpr…

线程状态:深入理解多任务并发编程中的精髓

目录 引言 1. 线程状态概述 1.1 定义 1.2 线程状态图 2. 线程状态的转换 2.1 新建到就绪 2.2 就绪到运行 2.3 运行到阻塞 2.4 运行到等待和超时等待 2.5 运行到终止 3. 实际编程中的线程状态管理 3.1 合理使用wait()和notify() 3.2 谨慎处理阻塞状态 3.3 使用线程…

力扣面试经典150题——Unix简化路径

https://leetcode.cn/problems/simplify-path/description/?envTypestudy-plan-v2&envIdtop-interview-150 思路&#xff1a;将串以/分割&#xff0c;判断字符串是…/./其他&#xff0c;进行入栈和出栈&#xff0c;最后留下的就是结果&#xff0c;拼装一下就好了。 三个…

设计模式之结构型模式(适配器、桥接、组合、享元、装饰者、外观、代理)

文章目录 一、结构型设计模式二、适配器模式三、桥接模式四、组合模式五、享元模式六、装饰者模式七、外观模式八、代理设计模式 一、结构型设计模式 这篇文章我们来讲解下结构型设计模式&#xff0c;结构型设计模式&#xff0c;主要处理类或对象的组合关系&#xff0c;为如何…

前后端数据传输格式(上)

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 作为后端&#xff0c;写…

Leetcode—198.打家劫舍【中等】

2023每日刷题&#xff08;五十二&#xff09; Leetcode—198.打家劫舍 算法思想 具体思路 首先&#xff0c;我们从上面的题目描述中抽象出题意。 ● 从一个非负整数数组中找到一个子序列&#xff0c;并且该子序列的和最大 ● 子序列中每个数的位置不能够相邻。举例来讲&…

【C语言】动态内存管理(C语言的难点与精华,数据结构的前置知识,你真的掌握了吗?)

文章目录 引言一、为什么要动态内存分配二、动态内存分配的相关函数2.1 malloc2.2 free2.3 calloc2.4 realloc 三、常见的动态内存的错误3.1 对NULL指针的解引用3.2 对动态内存越界访问3.3 对非动态内存释放3.4 对动态内存部分释放3.5 对动态内存多次释放3.6 未对动态内存释放&…

Java-JDBC操作MySQL

Java-JDBC操作MySQL 文章目录 Java-JDBC操作MySQL一、Java-JDBC-MySQL的关系二、创建连接三、登录MySQL四、操作数据库1、返回型操作2、无返回型操作 练习题目及完整代码 一、Java-JDBC-MySQL的关系 #mermaid-svg-B7qjXrosQaCOwRos {font-family:"trebuchet ms",verd…

邮政快递查询,邮政快递单号查询,按物流更新量筛选出需要的单号

批量查询邮政快递单号的物流信息&#xff0c;按物流更新量将需要的单号筛选出来。 所需工具&#xff1a; 一个【快递批量查询高手】软件 邮政快递单号若干 操作步骤&#xff1a; 步骤1&#xff1a;运行【快递批量查询高手】软件&#xff0c;并登录 步骤2&#xff1a;点击主界…

PHP短信接口防刷防轰炸多重解决方案三(可正式使用)

短信接口盗刷轰炸&#xff1a;指的是黑客利用非法手段获取短信接口的访问权限&#xff0c;然后使用该接口发送大量垃圾短信给目标用户 短信验证码轰炸解决方案一(验证码类解决)-CSDN博客 短信验证码轰炸解决方案二(防止海外ip、限制ip、限制手机号次数解决)-CSDN博客 PHP短信…

《opencv实用探索·八》图像模糊之均值滤波、高斯滤波的简单理解

1、前言 什么是噪声&#xff1f; 该像素与周围像素的差别非常大&#xff0c;导致从视觉上就能看出该像素无法与周围像素组成可识别的图像信息&#xff0c;降低了整个图像的质量。这种“格格不入”的像素就被称为图像的噪声。如果图像中的噪声都是随机的纯黑像素或者纯白像素&am…

Fiddler抓包模拟器(雷电模拟器)

Fiddler设置 List item 打开fiddler,的options 点击OK,重启fiddler 模拟器 更改网络设置 IP可以在电脑上终端上查看 然后在模拟器浏览器中输入IP:端口 安装证书

[二分查找双指针]LeetCode881: 救生艇

救生艇 作者推荐 [二分查找]LeetCode2040:两个有序数组的第 K 小乘积 本文涉及的基础知识点 二分查找算法合集 题目 给定数组 people 。people[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit。 每艘船最多可同时载两人&am…

[足式机器人]Part2 Dr. CAN学习笔记-数学基础Ch0-5Laplace Transform of Convolution卷积的拉普拉斯变换

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-数学基础Ch0-5Laplace Transform of Convolution卷积的拉普拉斯变换 Laplace Transform : X ( s ) L [ x ( t ) ] ∫ 0 ∞ x ( t ) e − s t d t X\left( s \right) \mathcal{L} \left[ x\lef…

QT作业2

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

【Flink系列三】数据流图和任务链计算方式

上文介绍了如何计算并行度和slot的数量&#xff0c;本文介绍Flink代码提交后&#xff0c;如何生成计算的DAG数据流图。 程序和数据流图 所有的Flink程序都是由三部分组成的&#xff1a;Source、Transformation和Sink。Source负责读取数据源&#xff0c;Transformation利用各种…

Linux各目录结构说明

文章目录 目录说明源码放哪里&#xff1f;拓展&#xff1a;Linux里面安装软件是装在home目录还是opt目录还是/usr/local好&#xff1f; bin boot dev etc home lib lib64 lostfound media mnt opt proc root run sbin srv sys tmp usr var 目录说明 bin 存放二进制可执行文件&…

《Spring Cloud Alibaba 从入门到实战》分布式配置

分布式配置 1、简介 Nacos 提供用于存储配置和其他元数据的 key/value 存储&#xff0c;为分布式系统中的外部化配置提供服务器端和客户端支持。 Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案&#xff0c;在特殊的 bootstrap 阶段&#xff0c;…

2023.12.4 关于 Spring Boot 统一异常处理

目录 引言 统一异常处理 异常全部监测 引言 将异常处理逻辑集中到一个地方&#xff0c;可以避免在每个控制器或业务逻辑中都编写相似的异常处理代码&#xff0c;这降低了代码的冗余&#xff0c;提高了代码的可维护性统一的异常处理使得调试和维护变得更加容易&#xff0c;通…

机器学习之无监督学习:九大聚类算法

今天&#xff0c;和大家分享一下机器学习之无监督学习中的常见的聚类方法。 今天&#xff0c;和大家分享一下机器学习之无监督学习中的常见的聚类方法。 在无监督学习中&#xff0c;我们的数据并不带有任何标签&#xff0c;因此在无监督学习中要做的就是将这一系列无标签的数…