【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;  // 指针数组的第一个元素指向 num1
    ptrArr[1] = &num2;  // 指针数组的第二个元素指向 num2
    ptrArr[2] = &num3;  // 指针数组的第三个元素指向 num3

    for (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 来访问和操作每个结构体对象的成员。通过输入每个学生的信息并输出学生信息,展示了动态分配内存和结构体指针的结合使用的一个简单例子。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React面试题(1)

1、什么是React&#xff1f; React是一个用于构建用户界面的JavaScript库。 2、React的特点是什么&#xff1f; React的主要特点包括&#xff1a; 组件化虚拟DOM单向数据流JSX语法高效的性能生态系统丰富 3、什么是JSX&#xff1f; JSX是一种JavaScript的语法扩展&#x…

C语言数据结构-----二叉树(1)认识数、二叉树、堆及堆的代码实现

前言 本篇文章讲述数、、二叉树、堆的基本概念和知识&#xff0c;以及堆的代码实现。 文章目录 前言1.树概念及结构1.1 树的定义1.2 树的基本概念1.3 如何区分树&#xff1f;1.4 二叉树1.5 二叉树的分类1.6 二叉树的存储结构 2.堆2.1 堆的基本概念2.2 堆的代码实现2.2.1 堆的…

【计算机网络】URL概念及组成

目录 前言 一. URL是什么 二. URL的组成 三. encode和decode 结束语 前言 本系列文章是计算机网络学习的笔记&#xff0c;欢迎大佬们阅读&#xff0c;纠错&#xff0c;分享相关知识。希望可以与你共同进步。 本篇讲解使用浏览器不可或缺的部分——URL 一. URL是什么 域…

前端使用视频作为背景图的方法

实现思路 通过 video source 引入视频&#xff0c;并对视频播放属性进行设置&#xff0c;再通过 css 使视频覆盖背景即可。 代码 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>有开发问题可联系作者</title>…

小白学java栈的经典算法问题——第四关白银挑战

内容1.括号匹配问题2.最小栈3.最大栈 1.括号匹配问题 栈的典型题目还是非常明显的&#xff0c;括号匹配、表达式计算等等几乎都少不了栈&#xff0c;本小节我们就看两个最经典的问题 首先是LeetCode20,链接 本道题还是比较简单的&#xff0c;其中比较麻烦的是如何判断两个符…

LeetCode刷题--- 求根节点到叶节点数字之和

个人主页&#xff1a;元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏&#xff1a;http://t.csdnimg.cn/ZxuNL http://t.csdnimg.cn/c9twt 前言&#xff1a;这个专栏主要讲述递归递归、搜索与回溯算法&#xff0c;所以下面题目主要也是这些算法做的 我讲述…

正则表达式:字符串处理的瑞士军刀

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

C++ Qt开发:字符串QString容器

在Qt框架中&#xff0c;QString 是一个强大而灵活的字符串容器&#xff0c;专为处理 Unicode 字符而设计。它提供了许多方便的方法来操作和处理字符串&#xff0c;使得在跨平台开发中能够轻松地进行文本操作。QString 是 Qt 开发中不可或缺的一部分&#xff0c;它的灵活性和强大…

Java9及之后关于类加载器的新特性

为了保证兼容性&#xff0c;JDK9没有从根本上改变三层类加载器的架构和双亲委派模型&#xff0c;但为了模块化系统的顺利运行&#xff0c;仍然发生了一些值得被注意的变动。 一、变动1 由于引入了模块化概念&#xff0c;所以不同的类加载器回去加载属于不同模块的类 启动类加…

打工人副业变现秘籍,某多/某手变现底层引擎-Stable Diffusion简介

Stable Diffusion是2022年发布的深度学习文本到图像生成模型,它主要用于根据文本的描述产生详细图像,尽管它也可以应用于其他任务,如

使用Android Studio导入Android源码:基于全志H713 AOSP,方便解决编译、编码问题

文章目录 一、 篇头二、 操作步骤2.1 编译AOSP AS工程文件2.2 将AOSP导入Android Studio2.3 切到Project试图2.4 等待index结束2.5 下载缺失的JDK 1.82.6 导入完成 三、 导入AS的好处3.1 本文案例演示源码编译错误AS对比同文件其余地方的调用AS错误提示依赖AS做错误修正 一、 篇…

字符串函数strtok

1.调用格式&#xff1a; 2.调用形式&#xff1a;char*strtok(char*p1,const char*p2),其中第二个是由分隔符组成的字符串&#xff0c;第一个为需要分隔的字符串 3.调用目的&#xff1a;将分隔符之间的字符串取出 4.调用时一般将源字符串拷贝后调用&#xff0c;因为此函数会将…

键盘打字盲打练习系列之循序渐进——4

一.欢迎来到我的酒馆 盲打&#xff0c;循序渐进&#xff01; 目录 一.欢迎来到我的酒馆二.继续练习二.矫正坐姿 二.继续练习 前面的章节&#xff0c;我们重点向大家介绍了主键盘区指法和键盘键位。经过一个系列的教程学习&#xff0c;相信大家对盲打这项技能已经掌握得差不多了…

金融量化交易:使用Python实现遗传算法

大家好&#xff0c;遗传算法是一种受自然选择过程启发的进化算法&#xff0c;用于寻找优化和搜索问题的近似解决方案。本文将使用Python来实现一个用于优化简单交易策略的遗传算法。 1.遗传算法简介 遗传算法是一类基于自然选择和遗传学原理的优化算法&#xff0c;其特别适用…

数据分析实例:基于电力大数据的中小型企业运营发展分析

前不久&#xff0c;帆软发起了【2023BI数据分析大赛】的活动&#xff0c;老李我也是这个大赛的评委。   今天跟大家分享的是基于电力大数据的中小型企业运营发展分析。 当我们去解读一份数据分析报告时&#xff0c;首先要了解这份报告的主要目的是什么&#xff0c;作者通过分…

mapbox使用v3版本,v2的样式切换不同时间段

创建DayAndNight.js /*** 使用方式* const dayNight new DayAndNight({ map: map // map 地图对象}) * 修改类型* dayNight.setConfigProperty(value)*/ class DayAndNight {constructor (sdMap) {this.map sdMap.mapthis.initStyle()}// 初始化时添加必要样式initStyle () {…

vue中设置滚动条的样式

在vue项目中&#xff0c;想要设置如下图中所示滚动条的样式&#xff0c;可以采用如下方式&#xff1a; ​// 直接写在vue.app文件中 ::-webkit-scrollbar {width: 3px;height: 3px; } ::-webkit-scrollbar-thumb { //滑块部分// border-radius: 5px;background-color: #1890ff;…

excel数据重复率怎么计算【保姆教程】

大家好&#xff0c;今天来聊聊excel数据重复率怎么计算&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; excel数据重复率怎么计算 在Excel中计算数据重复率可以通过以下步骤实现&#xff1a; 1. 确定重复…

Java并发编程-synchronized、volatile、AQS解析

Java并发编程 synchronized 如何保证线程安全 JDK1.6 之前&#xff0c;synchronized 是一个重量级锁相比于JUC的锁显得非常笨重&#xff0c;存在性能问题 JDK1.6 及之后&#xff0c;Java 对 synchronized 进行的了一系列优化&#xff0c;性能与 JUC 的锁不相上下 synchroni…

python源码,在线读取传奇列表,并解析为需要的JSON格式

python源码&#xff0c;在线读取传奇列表&#xff0c;并解析为需要的JSON格式 [Server] ; 使用“/”字符分开颜色&#xff0c;也可以不使用颜色&#xff0c;支持以前的旧格式&#xff0c;只有标题和服务器标题支持颜色 ; 标题/颜色代码(0-255)|服务器标题/颜色代码(0-255)|服务…