当前位置: 首页 > news >正文

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

 野指针:

 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 arrshowArr(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

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

 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python 如何操作 Excel 文件(openpyxl, xlrd)
  • 基于STM32开发的智能农业监测与控制系统
  • 【深度学习】迭代次数 vs bs? 迭代次数 vs epoch
  • Vue.js 样式绑定
  • Systemc example based on VCS
  • 专家系统的核心要点解析|专家系统|人工智能|知识工程
  • 【中仕公考是骗子吗】公务员联考是什么意思?
  • 线性代数基础
  • 基于ssm+vue+uniapp的图书管理系统小程序
  • 关于武汉芯景科技有限公司的实时时钟芯片XJ8340开发指南(兼容DS1340)
  • 【微服务】springboot整合对象映射工具MapStruct使用详解
  • 力扣刷题--137. 只出现一次的数字 II【中等】
  • FATE Board 执行流程探索
  • SpringBoot依赖之Spring Boot DevTools热部署开发增效工具
  • 编写测试用例的常用方法总结
  • IE9 : DOM Exception: INVALID_CHARACTER_ERR (5)
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • axios请求、和返回数据拦截,统一请求报错提示_012
  • Codepen 每日精选(2018-3-25)
  • If…else
  • JavaScript 一些 DOM 的知识点
  • npx命令介绍
  • PHP 小技巧
  • vue脚手架vue-cli
  • 百度地图API标注+时间轴组件
  • 机器学习学习笔记一
  • 强力优化Rancher k8s中国区的使用体验
  • 人脸识别最新开发经验demo
  • 入手阿里云新服务器的部署NODE
  • 项目实战-Api的解决方案
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 移动端解决方案学习记录
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​如何使用QGIS制作三维建筑
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • # 移动硬盘误操作制作为启动盘数据恢复问题
  • #AngularJS#$sce.trustAsResourceUrl
  • #define 用法
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • (2024)docker-compose实战 (8)部署LAMP项目(最终版)
  • (第二周)效能测试
  • (二开)Flink 修改源码拓展 SQL 语法
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)php新闻发布平台 毕业设计 141646
  • (离散数学)逻辑连接词
  • (六)Hibernate的二级缓存
  • .NET C# 配置 Options
  • .NET Compact Framework 3.5 支持 WCF 的子集
  • .Net Core中的内存缓存实现——Redis及MemoryCache(2个可选)方案的实现
  • .net framework profiles /.net framework 配置
  • .NET 跨平台图形库 SkiaSharp 基础应用
  • .net 流——流的类型体系简单介绍
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。
  • .net6+aspose.words导出word并转pdf