指针的一些细节补充———C语言

news2024/11/17 9:27:46

 野指针:

 1.未初始化的指针

eg:
int *p;       // 未初始化的指针
*p = 5;       // 未定义行为,p 是野指针
———————————————————————————————————————————————————————————————————————————————————————————
//解决方法:
//在动态内存开辟完成后应该进行检查
int *p = (int *)malloc(sizeof(int));
if (p == NULL) {
    // 处理内存分配失败的情况
    return -1;
}
———————————————————————————————————————————————————————————————————————————————————————————
//进行及时的初始化
int value = 42;
int *p = &value;  // 在声明时初始化

2.指向已经释放的内存

//动态内存释放后继续使用指针:
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *p = (int *)malloc(sizeof(int));  // 动态分配内存
    *p = 42;                              // 使用内存

    free(p);                              // 释放内存
    *p = 24;  // 错误:悬空指针访问,未定义行为
//解决方法:
//应该将指针进行滞空
    free(p);
    p = NULL;

    printf("%d\n", *p);  // 未定义行为,输出可能随机
    return 0;
}
—————————————————————————————————————————————————————————————————————————————————————————
//进行重复的释放:
#include <stdlib.h>

int main() {
    int *p = (int *)malloc(sizeof(int));

    free(p);   // 第一次释放
    free(p);   // 错误:重复释放,未定义行为
//解决方法:
//进行重复释放的判断
if (p != NULL) {
    free(p);
    p = NULL;
}
    return 0;
}
—————————————————————————————————————————————————————————————————————————————————————————
//指针副本仍指向已释放的内存
#include <stdio.h>
#include <stdlib.h>

int main() {
    int *p1 = (int *)malloc(sizeof(int));  // 动态分配内存
    int *p2 = p1;                          // p2 也是悬空指针
    free(p1);  // 释放内存,p1和p2现在都指向已释放的内存
    // 任何对p2的访问都是未定义行为
    *p2 = 10;  // 未定义行为
    printf("%d\n", *p2);  // 未定义行为
    return 0;
}

3.指向超出变量生命周期的内存

//指向函数内局部变量的指针:
#include <stdio.h>

int* getPointer() {
    int x = 10;  // 局部变量 x 的生命周期在函数结束时终止
    //在int前加static使用静态变量
    return &x;   // 返回局部变量的地址,危险操作,返回后就已经是悬空指针了
}

int main() {
    int *p = getPointer();  // p 现在是一个悬空指针
    printf("%d\n", *p);     // 未定义行为,可能会打印垃圾值或导致程序崩溃
    return 0;
}
—————————————————————————————————————————————————————————————————————————————————————————
//指向作用域内局部变量的指针
#include <stdio.h>

int* pointerOutsideScope() {
    int *p;
    {
        int y = 20;  // y 是代码块内的局部变量
        p = &y;      // p 指向 y 的内存地址
    }
    // 此时 y 的生命周期结束,p 是一个悬空指针
    return p;
//使用
    int *p = (int *)malloc(sizeof(int));
    *p = 10;  // 动态内存的生命周期由程序员控制
    return p;
}

int main() {
    int *ptr = pointerOutsideScope();
    printf("%d\n", *ptr);  // 未定义行为,可能打印垃圾值
    return 0;
}
 

4.指向已经重新分配的内存

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

int main() {
    int *p = (int *)malloc(10 * sizeof(int));  // 分配内存
    if (p == NULL) {
        printf("Memory allocation failed\n");
        return -1;
    }
    // 初始化数组
    for (int i = 0; i < 10; i++) {
        p[i] = i + 1;  
    }

    int *q = p;  // q 和 p 指向同一块内存

    p = (int *)realloc(p, 20 * sizeof(int));  // 重新分配内存

    if (p == NULL) {
        printf("Memory reallocation failed\n");
        free(q);  // 如果 realloc 失败,释放原内存
        return -1;
    }

    // q 现在是悬空指针,因为内存可能已经被移动
    printf("%d\n", q[0]);  // 未定义行为,q 指向无效内存
    free(p);  // 释放新的内存块
    return 0;
}

指针运算:

1.指针+-整数

如何获取数组中最后一个元素的地址arr+size-1 或 &arr[size-1]

#define N_VALUES 5 // 定义数组的长度
#include <stdio.h>
int main() {
float values[N_VALUES] = { -1 };
float* vp;
for (vp = &values[0]; vp < &values[N_VALUES];) {
*vp++ = 0;
}
return 0;
}

2.指针-指针

会得到两个指针中间元素的个数

int main() {
int arr[5] = { 13,34,21,38,49 };
int res = &arr[4] - &arr[0];
printf("%d\n", res);
return 0;
}

75bbca418f8346eca9516f75d3b9e061.png

指针的关系运算

#define N_VALUES 5 // 定义数组的长度
#include <stdio.h>
int main() {
    float values[N_VALUES] = { -1 };
    float* vp;
    for (vp = &values[N_VALUES]; vp > &values[0];) {
        *vp++ = 0;
    }
    return 0;
}

允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。

指针函数:

本质是函数不过返回值是地址

#include <stdio.h>
float* designArray(int* p_length){
    static float arr[]={68.5,75.4,69.8,90,75.6,78};
    int size = sizeof(arr)/sizeof(arr[0]);
    *p_length = size;
    return arr;//返回的是一个地址
}
void showArr(float* arr,int length){
    for(int i=0;i<length;i++){
        printf("%-8.2f",*(arr+i));
    }
    printf("\n");
}
int main()
{
    int length = 0;
    float* result = designArray(&length);
//ouput arr
    showArr(result,length);
    return 0;
}

函数指针:

指向函数的指针

#include <stdio.h>
int getMax(int a,int b){
    //对应的指针类型int (*)(int,int)
    return a>b?a:b;
}
int main()
{
    int a=0,b=0;
    printf("input two data:");
    scanf("%d%d",&a,&b);
    int max = getMax(a,b);
    printf("The maximum values of %d and %d are %d\n",a,b,max);
return 0;
}

回调函数

#include <stdio.h>
int add(int a,int b){
return a + b;
}
int sub(int a,int b){
return a - b;
}
int calc(int a,int b,int (*pfun)(int,int)){
    return pfun(a,b);
}
int main(){
    int a=0,b=0;
    printf("input two data:");
    scanf("%d%d",&a,&b);
    int result = calc(a,b,add);//在一个函数中调用另一个函数
    printf("a + b = %d\n",result);
    result = calc(a,b,sub);
    printf("a - b = %d\n",result);
return 0;
}

36302c9e504f436c9b27dfd6482546bf.png

  • 这是本人的学习笔记不是获利的工具,小作者会一直写下去,希望大家能多多监督我
  • 文章会每攒够两篇进行更新发布(受平台原因,也是希望能让更多的人看见)
  • 感谢各位的阅读希望我的文章会对诸君有所帮助

 

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

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

相关文章

记Codes 开源研发项目管理平台——管理系统颠覆性创新实现之事件驱动+信息流

引言 市面上所有管理系统&#xff0c;数据都不是以推流的方式展现到前端&#xff0c;有新数据产生需主动刷新页面才能看到&#xff0c;也就是“人找事”&#xff1b;而不是主动推送的“事找人”&#xff0c;Codes 敢为人先&#xff0c;采用事件驱动信息流实现“事找人”。 1、…

一起学习LeetCode热题100道(64/100)

64.搜索二维矩阵(学习) 给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a; 每行中的整数从左到右按非严格递增顺序排列。 每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&am…

Java Excel转PDF(免费)

目前市面上 Excel 转 PDF 的组件较多&#xff1a; 收费&#xff1a;aspose、GcExcel、spire开源&#xff1a;jacob、itextpdf 其中收费的组件封装得比较好&#xff0c;代码简洁&#xff0c;转换的效果也很好&#xff0c;但收费也高得离谱&#xff1a; 为了成本考虑&#xff…

共享单车|基于SprinBoot+vue的共享单车数据储存系统(源码+数据库+文档)

共享单车数据储存系统 基于SprinBootvue的共享单车数据储存系统 一、前言 二、系统设计 三、系统功能设计 系统登录注册实现 管理员模块实现 用户模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介…

STM32和TMSF28335定时器的系统时钟问题

用户可通过多个预分频器配置AHB、高速APB(APB2)和低速APB(APB1)域的频率。AHB和APB2域的最大频率是72MHz。APB1域的最大允许频率是36MHz。 定时器时钟频率分配由硬件按以下2种情况自动设置&#xff1a; 如果相应的APB预分频系数是1&#xff0c;定时器的时钟频率与所在APB总线…

俄罗斯OZON真的适合小白做吗,有哪些坑需要知道

OZON 对于小白来说有一定的可行性&#xff0c;但也存在一些需要注意的 “坑”&#xff1a; OZON 平台适合小白的原因&#xff1a; 入驻门槛较低&#xff1a;目前中国卖家入驻 OZON 是免费的&#xff0c;具备企业营业执照&#xff08;暂不支持个体工商户注册&#xff09;&#…

Part4-DOM学习笔记-获取元素属性及节点操作

6.获取元素属性 6.1 获取元素属性 获取元素的属性有两种方式&#xff1a; element.属性&#xff1a; 获取内置属性值&#xff0c;元素本身自带的属性 不能获取自定义属性 代码示例如 console.log(div.id)element.getAttribute(‘属性’)&#xff1a; 可以获取内置属性值 可…

高带宽云服务器有什么用处?这几种用处要知道

高带宽云服务器的主要用途包括提供更快的网络连接速度、支持高并发访问和大规模数据传输、提高应用程序的性能和用户体验等。在当今数字化时代&#xff0c;随着大数据、云计算、流媒体等技术的飞速发展&#xff0c;高带宽云服务器已成为许多企业和个人用户的首选。以下将详细分…

C++ PCL求解法向量及可视化

【版权声明】本文为博主原创文章&#xff0c;未经博主允许严禁转载&#xff0c;我们会定期进行侵权检索。 参考书籍&#xff1a;《人工智能点云处理及深度学习算法》 本文为专栏《Python三维点云实战宝典》系列文章&#xff0c;专栏介绍地址“【python三维深度学习】python…

C语言sprintf函数使用

1 其函数原型为&#xff1a;int sprintf(char *str, const char *format,...)。 具体用法如下&#xff1a; 基本语法&#xff1a; str&#xff1a;目标字符串的指针&#xff0c;用于存储格式化后的结果。format&#xff1a;格式化字符串&#xff0c;用于指定输出的格式。后续是…

IP地址SSL证书要怎么申请?

申请IP地址SSL证书的过程可以简化为以下四个步骤&#xff1a; 1. 选择证书提供商 确定需求&#xff1a;首先&#xff0c;明确你的需求&#xff0c;包括所需的证书类型&#xff08;如IP地址证书&#xff09;和加密算法等。选择CA机构&#xff1a;选择一个受信任的证书颁发机构…

有了这款低代码工具,从此让你告别烦人的996报表制作模式

一、低代码平台兴起的背景 近年来&#xff0c;低代码与零代码平台的兴起&#xff0c;无疑是IT领域的一股强劲风潮&#xff0c;它们依托互联网技术的飞速进步&#xff0c;致力于简化软件开发流程&#xff0c;推动工具向更加易用、高效的方向演进。在这一浪潮中&#xff0c;尽管…

重塑工程机械设备市场:创新网络推广方案引领潮流

在重塑工程机械设备领域&#xff0c;网络营销推广已日益凸显为企业拓展市场版图、提升品牌知名度不可或缺的关键手段。鉴于互联网时代的海量信息与激烈竞争&#xff0c;关键词搜索排名优化更是成为了衡量网络推广成效的重要标尺。为了在这场数字战役中脱颖而出&#xff0c;我们…

二、测试的基本概念

文章目录 一、需求&#xff08;一&#xff09;需求的概念&#xff08;二&#xff09;用户需求&#xff08;三&#xff09;软件需求 二、从软件测试人员角度看需求&#xff08;一&#xff09;为什么需求对软件测试人员如此重要&#xff08;二&#xff09;如何才可以深入理解被测…

【论文速读】| ARVO: 开源软件可重现漏洞的全景图

本次分享论文&#xff1a;ARVO: Atlas of Reproducible Vulnerabilities for Open Source Software 基本信息 原文作者&#xff1a;Xiang Mei, Pulkit Singh Singaria, Jordi Del Castillo, Haoran Xi, Abdelouahab (Habs) Benchikh, Tiffany Bao, Ruoyu Wang, Yan Shoshitai…

Java Email发送:如何配置SMTP服务器发信?

Java Email发送性能如何优化&#xff1f;怎么实现Java发信功能&#xff1f; Java Email发送功能使得开发者能够轻松集成邮件服务到他们的应用程序中。通过配置SMTP服务器&#xff0c;Java Email发送可以实现高效、可靠的邮件传递。AokSend将详细介绍如何配置SMTP服务器以进行J…

10、ollama启动LLama_Factory微调大模型(llama.cpp)

在前面章节中介绍了如何使用LLama_Factory微调大模型&#xff0c;并将微调后的模型文件合并导出&#xff0c;本节我们我们看下如何使用ollama进行调用。 1、llama.cpp LLama_Factory训练好的模型&#xff0c;ollama不能直接使用&#xff0c;需要转换一下格式&#xff0c;我们…

Java面试——Spring

优质博文&#xff1a;IT-BLOG-CN 一、Spring Bean 作用域 【1】singleton&#xff1a;该属性在 IOC容器仅创建一个 Bean实例&#xff08;单例&#xff09;&#xff0c;IOC容器每次返回的是同一个 Bean实例。 【2】prototype&#xff1a;该属性在 IOC容器可以创建多个 Bean实例…

MT3608L 2.5A,高效率1.2MHz电流模式升压转换器芯片IC

一般描述 MT3608L是一款恒频、6针SOT23电流模式升压转换器&#xff0c;适用于小型、低功率应用。MT3608L开关频率为1.2 MHz&#xff0c;允许使用高度小于2mm的微型、低成本电容器和电感器。内部软启动可产生小浪涌电流&#xff0c;延长电池寿命。 MT3608L具有在…

事半功倍:利用增强现实提高工作效率

人们通常认为增强现实只是游戏中的一个强大的功能&#xff0c;然而&#xff0c;研究表明&#xff0c;增强现实在提高工厂的效率和生产力方面也发挥着重要作用。不管增强现实、虚拟现实还是混合现实都能很好地模拟工厂的工作场景&#xff0c;这对于培训、运营、安全和研发方面的…