C语言基础14(动态内存控制后续)

news2024/12/16 15:22:06

文章目录

    • 野指针、空指针、空悬指针
      • 野指针
      • 空指针
      • 空悬指针
    • void与void*的区别
    • 内存操作
      • 常用内存操作函数
        • 内存填充
        • 内存拷贝
        • 内存比较
        • 内存查找

野指针、空指针、空悬指针

野指针

定义:指向一块未知区域(已经销毁或者访问受限的内存区域外的已存在或不存在的内存区域),被称作野指针。野指针是危险的

危害:

①引用野指针相当于访问了非法的内存,常常会导致段错误(segmentation fault),也有可能编译运行不报错

②引用野指针,可能会破坏系统的关键数据,导致系统崩溃等严重后果

野指针产生的场景:

1.变量未初始化,通过指针访问该变量

int a;
int *p = &a;//p是野指针
printf("%d\n",*p);//访问野指针,数据不安全

2.指针变量未初始化

int *p;//p是野指针
printf("%d\n",*p);

int a = get();
p = &a;

3.指针指向的内存空间被(free)回收了

int *p = malloc(4);
*p = 12;//此时的p不是野指针
free(p);
printf("%d\n",*p);

4.指针函数中直接返回了局部变量的地址

int* get_num()   
{
    int a = 15;
    int *p = &a;//此时p对应的数据是一个局部作用域的数据
    return p;
}
main()
{
    int *p = get_num();//此时p是野指针
}

如何避免野指针

1.指针变量要及时初始化,如果暂时没有对应的值,建议赋初值NULL

2.数组操作(遍历和指针运算)时,注意数组的长度,避免越界

3.指针指向的内存空间被回收,建议给这个指针变量赋值为NULL

int *p = (int *)malloc(10);
free(p);
p = NULL;

4.指针变量使用之前要检查它的有效性(非空校验)

int* p = NULL;
//if(p == NULL)
if(!p)//!p等价于p == NULL
{
    return -1;
}

空指针

很多情况下,我们不可避免的会遇到野指针,比如刚定义的指针无法立即为其分配一块恰当的内存,又或者指针指向的内存已经被释放了等等。一般的做法是将这些危险的野指针指向一块确定的内存,比如零地址内存(NULL)

在这里插入图片描述
定义:空指针即保存了零地址的指针(赋值为NULL的指针),也就是指向零地址的指针(NULL是空常量,它的值是0,这个NULL一般存放在内存0x0000 0000的位置,这个地址只能存NULL,不能被其他程序修改)

示例:

//1.刚定义的指针,让其指向零地址以确保安全
char *p1 = NULL;
int* p2 = NULL; 

//2.被释放了内存的指针,让其指向零地址以确保安全
char *p3 = malloc(100);
free(p3);
p3 = NULL;

int sum = 0; 

空悬指针

在C语言中,悬空指针指的是指向已删除(或释放)的内存地址位置的指针。如果一个指针指向的内存已经被释放,但指针本身并未重新指向其他有效的内存地址,那么这个指针就变成了悬空指针。悬空指针会引发不可预知的错误,并且如果一旦发生,就很难定位,因此在编程中尽量避免使用悬空指针

char *p3 = malloc(100);
free(p3);
printf("%p,%c\n",p3,*p3);

void与void*的区别

定义:

  • void:是空类型,是数据类型的一种
  • void* :是指针类型,是指针类型的一种,可以匹配任意类型的指针,类似于通配符,又被叫做万能指针

void:

  • 说明:void作为返回值类型使用,表示没有返回值;作为形参,表示形参列表为空,在调用的时候不能给实参
  • 举例:
//函数定义
void fun(void){..}//等效于 void fun(){..}
//函数调用
fun();

void*:

  • 说明:
    • void*是一个指针类型,但该指针的数据类型不明确,无法通过解引用获取内存中的数据,因为void*不知道访问几个内存单元
    • void*是一种数据类型,可以作为函数返回值类型,也可以作为形参类型
    • void* 类型的变量在使用之前必须强制类型转换,明确它能够访问几个字节的内存空间
int *p = (int*)malloc(4);
  • 说明:
    • void*作为返回值类型,这个函数可以返回任意类型的指针
    • void*作为形参类型,这个函数在调用时,可以给任意类型的指针
  • 总结:
    • void*类似于通配符,不能对void*类型的变量解引用(因为不明确数据类型,所以无法确定内存单元的大小)
    • void*在间接访问(解引用)前要强制类型转换,但不能太随意,否则存和取的数据类型不一致

内存操作

我们对于内存的操作需要依赖string库(对应的头文件string.h)完成内存的操作

常用内存操作函数

内存填充
  • 头文件:#include <string.h>

  • 函数原型:void* memeset(void* s,int c,size_t n)

  • 函数功能:填充s开始的堆内存空间前n个字节,使得每个字节值为c

  • 函数参数:

    • void* s:代操作内存首地址
    • int c:填充的字节数据
    • size_t n:填充的字节数
  • 返回值:返回s

  • 注意:c常常设置为0,用于动态内存初始化

内存拷贝
  • 头文件:#include <string.h>

  • 函数原型:void* memcpy(void* dest,const void* src,size_t n) 适合目标地址与源地址内存无重叠的情况

    void* memove(void* dest,const void* src,size_t n)

  • 函数功能:拷贝src开始的堆内存空间前n个字节,到dest对应的内存中

  • 函数参数:

    • void* dest:目标内存首地址
    • void* src:源内存首地址
    • size_t n:拷贝的字节数
  • 返回值:返回dest

  • 注意:内存申请了几个内存空间,就访问几个内存空间,否则数据不安全

  • 案例:

#include <stdio.h>
#include <string.h>

int main(int argc,char *argv[])
{
    //创建源空间和目标空间
    int src[4] = {11,22,33,44};
    int dest[6] = {111,222,333,444,555,666};

    //将src中的数据拷贝到dest
    memmove(dest,src,2*sizeof(int));
    printf("%d\n",dest[0]);
    return 0;
}

内存比较
  • 头文件:#include <string.h>
  • 函数原型:int memcmp(void *dest,const *src,size_t n)
  • 函数功能:比较src和dest所代表的内存前n个字节的数据
  • 函数参数:
    • void* dest:目标内存首地址
    • const void* src:源内存首地址
    • size_t n:比较的字节数
  • 返回值:
    • 0:数据相同
    • >0:dest中的数据大于src
    • <0:dest中的数据小于src
  • 注意:n建议和src,dest的总容量一致;如果不一致,内存比较的结果就不确定了

案例:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc,char *argv[])
{
    //申请内存
    int* src = (int*)malloc(3*sizeof(int));
    int* dest = (int*)calloc(4,sizeof(int));
    
    if(!src || !dest)
    {
        perror("内存申请失败!");
        return -1;
    }
    //对使用malloc申请的空间清零
    bzero(src,3*sizeof(int));
    
    *src = 65;
    *(src+1) = 66;

    *dest = 70;
    *(dest+1) = 55;
    
    int result = memcmp(dest,src,2*sizeof(int));

    char *a = (char*)src;
    char *b = (char*)dest;

    int result2 = memcmp(b,a,1*sizeof(char));
    printf("%d,%d\n",result,result2);

    free(src);
    free(dest);
    src = NULL;
    dest = NULL;
    return 0;
}

在这里插入图片描述

内存查找
  • 头文件:#include <string.h>
  • 函数原型:`int *memchr| *memrchr(const void *s,int c,size_t n)
  • 函数功能:在s开始的堆内存空间前n个字节中查找字节数据c
  • 函数参数:
    • const void *s: 代操作内存首地址
    • int c:待查找的字节数据
    • size_t n:查找的字节数
  • 返回值:返回查找到的字节数据地址
  • 注意:如果内存中没有重复数据,memchr和memrchr

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS在线格式化 - 加菲工具

CSS在线格式化 打开网站 加菲工具 选择“CSS在线格式化” 或者直接访问 https://www.orcc.online/tools/css 输入CSS代码&#xff0c;点击左上角的“格式化”按钮 得到格式化后的结果

分布式事物XA、BASE、TCC、SAGA、AT

分布式事务——Seata 一、Seata的架构&#xff1a; 1、什么是Seata&#xff1a; 它是一款分布式事务解决方案。官网查看&#xff1a;Seata 2.执行过程 在分布式事务中&#xff0c;会有一个入口方法去调用各个微服务&#xff0c;每一个微服务都有一个分支事务&#xff0c;因…

Serdes技术与Xilinx GT概览

目录 一、前言 二、Serdes技术 2.1 芯片间信号传输 2.2 Serdes技术 三、 Xilinx GT 3.1 7系列器件GT 3.2 Ultrascale GT 3.3 Ultrascale GT 四、参考资料 一、前言 对于芯片间高速信号传输技术&#xff0c;不得不提serdes以及在Xilinx在此基础上的高速收发器GT系列&…

HarmonyOS Next 元服务新建到上架全流程

HarmonyOS Next 元服务新建到上架全流程 接上篇 这篇文章的主要目的是介绍元服务从新建到上家的完整流程 在AGC平台上新建一个项目 链接 一个项目可以多个应用 AGC新建一个元服务应用 新建一个本地元服务项目 如果成功在AGC平台上新建过元服务&#xff0c;那么这里会自动显…

【Spark】Spark的两种核心Shuffle工作原理详解

如果觉得这篇文章对您有帮助&#xff0c;别忘了点赞、分享或关注哦&#xff01;您的一点小小支持&#xff0c;不仅能帮助更多人找到有价值的内容&#xff0c;还能鼓励我持续分享更多精彩的技术文章。感谢您的支持&#xff0c;让我们一起在技术的世界中不断进步&#xff01; Sp…

【CSS in Depth 2 精译_079】第 13 章:渐变、阴影与混合模式概述 + 13.1:CSS 渐变效果(一)——使用多个颜色节点

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 13 章 渐变、阴影与混合模式】 ✔️ 13.1 渐变 ✔️ 13.1.1 使用多个颜色节点&#xff08;一&#xff09; ✔️13.1.2 颜色插值13.1.3 径向渐变13.1.4 锥形渐变 文…

Linux 中的 mkdir 命令:深入解析

在 Linux 系统中&#xff0c;mkdir 命令用于创建目录。它是文件系统管理中最基础的命令之一&#xff0c;广泛应用于日常操作和系统管理中。本文将深入探讨 mkdir 命令的功能、使用场景、高级技巧&#xff0c;并结合 GNU Coreutils 的源码进行详细分析。 1. mkdir 命令的基本用法…

mp4影像和m4a音频无损合成视频方法

第一步&#xff1a;复制高清视频地址 url 第二步:打开网址粘贴复制的视频url视频下载 第三步&#xff1a;下载-影像.mp4和-音频.m4a 第四步&#xff1a;合并视频&#xff1b; 使用ffmpeg进行无损合成&#xff08;如果没有安装ffmpeg请自行下载安装下载 FFmpeg (p2hp.com)&…

Leonardo.Ai丨一键生成图片(AI绘图)

随着人工智能技术的迅速发展,AI在各个领域的应用越来越广泛,特别是在图像生成方面。AI艺术创作的崛起,不仅让艺术创作变得更加便捷和创新,也为设计师、艺术家及普通用户提供了全新的工具。Leonardo.Ai作为一款基于人工智能的图像生成工具,通过简洁的操作和强大的功能,成功…

简单的Java小项目

学生选课系统 在控制台输入输出信息&#xff1a; 在eclipse上面的超级简单文件结构&#xff1a; Main.java package experiment_4;import java.util.*; import java.io.*;public class Main {public static List<Course> courseList new ArrayList<>();publi…

Android实现RecyclerView边缘渐变效果

Android实现RecyclerView边缘渐变效果 1.前言&#xff1a; 是指在RecyclerView中实现淡入淡出效果的边缘效果。通过这种效果&#xff0c;可以使RecyclerView的边缘在滚动时逐渐淡出或淡入&#xff0c;以提升用户体验。 2.Recyclerview属性&#xff1a; 2.1、requiresFading…

Avalonia的Ribbon

将以前Avalonia项目中的Ribbon单独隔离&#xff0c;提交到了github,方便大家查看修改。 Ribbon做成了组件&#xff0c;但是想要界面效果&#xff0c;还得结合窗体功能开发。 项目地址&#xff1a; jinyuttt/AvaloniaRibbonUI: AvaloniaRibbon component

Vue04

目录 一、学习目标 1.组件的三大组成部分&#xff08;结构/样式/逻辑&#xff09; 2.组件通信 3.综合案例&#xff1a;小黑记事本&#xff08;组件版&#xff09; 4.进阶语法 二、scoped解决样式冲突 1.默认情况&#xff1a; 三、data必须是一个函数 1、data为什么要写…

C# 探险之旅:第十八节 - 元组(Tuple):神奇的背包与丢弃的艺术,还有变身大法!

嘿&#xff0c;探险家们&#xff01;欢迎再次踏上C#的奇妙旅程。今天&#xff0c;我们要聊的是一个非常实用又有点懒散的旅行伴侣——元组&#xff08;Tuple&#xff09;。想象一下&#xff0c;你正准备来一场说走就走的旅行&#xff0c;但是不想带太多行李&#xff0c;只想简单…

SAP软件如何启用反记账功能

SAP软件和国内ERP软件不一样&#xff0c;它在录入会计凭证时是不可以录入负数的&#xff08;即红冲凭证&#xff09;&#xff0c;因此无法直接实现传统意义上的红字冲销。 比如&#xff0c;如下SAP正常和冲销业务产生会计凭证如下&#xff1a; 正常的业务凭证&#xff1a; 借…

若依-帝可得app后端

视频地址 https://www.bilibili.com/video/BV1pf421B71v?t=510.1 APP后端技术栈 架构解析 验证码功能 开发环境使用改的是固定的验证码 12345正式环境使用的是 阿里云的短信方案@Override public void sendSms(String mobile) {// String code = RandomUtil.randomNumbers(5);…

金融分析-Transformer模型(基础理论)

Transformer模型 1.基本原理 transformer的core是注意力机制&#xff0c;其本质就是编码器-解码器。他可以通过多个编码器进行编码&#xff0c;再把编码完的结果输出给解码器进行解码&#xff0c;然后得到最终的output。 1.1编码器 数据在编码器中会经过一个self-attention的…

JS-手写new

我们先再来理一理原型 Object1 {name:deng,age:18 } Object2 {name:ru,age:18 } const Person function(){} Person.prototype Object1; const p1 new Person(); console.log(p1.name); //deng Person.prototype null; console.log(p1.name); //deng上面给Person的构造函…

深圳国威HB1910数字IP程控交换机 generate.php 远程命令执行漏洞复现

0x01 产品描述: 深圳国威主营国威模拟、数字、IP 交换机、语音网关、IP 电话机及各种电话机。深圳国威电子有限公司HB1910是一款功能强大的网络通信设备,适用于各种企业通信需求。 0x02 漏洞描述: 深圳国威电子有限公司HB1910数字IP程控交换机generate.php存在远程命令执行…

机器学习预处理-表格数据的分析与可视化

机器学习预处理-表格数据的分析与可视化 最近在做一些模型部署的工作&#xff0c;但是发现对于数据的处理、分析、训练方面还是缺少一些系统的学习&#xff0c;因此抽空余时间分析总结一些使用python进行数据处理的实用案例&#xff0c;希望能够方便自己已经其他人的Ctrl CV。…