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

c语言中函数传递二级指针,修改指针指向

#include<stdio.h>voidtry_change_ptr(int*p){// 发现p指向的地址和ptr指向的地址一样,但是p本身的地址和ptr本身的地址不一样printf("Inside function, p = %p, &p = %p\n",(void*)p,&p);// 所以可以修改p指向的内容*p=1;// 但修改不了ptr的指向地址,因为p是一个拷贝,p本身的地址和ptr本身的地址不一样p=NULL;// 修改的是函数内部的 p(副本)printf("Inside function, p = %p, &p = %p\n",(void*)p,&p);}intmain(){inta=10;int*ptr=&a;printf("&a %p\n",&a);printf("%d\n",*ptr);// 打印ptr的指向地址和ptr本身的地址printf("Before call, ptr = %p, &ptr = %p \n",(void*)ptr,&ptr);//这里会创建副本,就像int fun(int a) 传入a一样,如果要修改a的地址,就要传a的地址try_change_ptr(ptr);printf("After call, ptr = %p, &ptr = %p \n",(void*)ptr,&ptr);// 仍然是 &a!没变!printf("%d\n",a);return0;}/* &a 0000002274F4FB60 10 Before call, ptr = 0000002274F4FB60, &ptr = 0000002274F4FB68 Inside function, p = 0000002274F4FB60, &p = 0000002274F4FB40 Inside function, p = 0000000000000000, &p = 0000002274F4FB40 After call, ptr = 0000002274F4FB60, &ptr = 0000002274F4FB68 1 *//*如果你不仅想修改内容,还想在函数内部改变原指针的指向,你需要使用二级指针(指针的指针)。 这就像你不仅拿到了钥匙,还拿到了“存放钥匙的保险箱的钥匙”。*///void changePointer(int **p) {// **p = 200; // 依然可以修改内容// *p = NULL; // 成功修改了外部指针的指向!//}//int main() {// int a = 10;// int *ptr = &a;// changePointer(&ptr); // 注意这里传的是 ptr 的地址// // 此时 ptr 已经变成了 NULL// return 0;//}/* * 输出打印 Before call, ptr = 0060FE98 Inside function, *p = 10 Inside function, p = 00000000 After call, ptr = 0060FE98 *///void really_change_ptr(int **pp)//{// //和a的地址相同// printf("Inside function, *pp = %p\n", *pp);// printf("Inside function, **pp = %d\n", **pp);// *pp = NULL; // 通过 pp 修改它指向的那个指针变量// printf("Inside function, pp = %p\n", (void *) pp);// printf("Inside function, *pp = %p\n", *pp);//}//int main()//{// int a = 10;// printf("a add: %p\n", &a);// int *ptr = &a;// printf("Before: %p\n", (void *) ptr);// //这里要修改指针的地址,就要通过指针类型,传指针的地址// really_change_ptr(&ptr); // 传 ptr 的地址// printf("After: %p\n", (void *) ptr); // 现在变成 NULL 了!//}/* a add: 0060FE9C Before: 0060FE9C Inside function, *pp = 0060FE9C Inside function, **pp = 10 Inside function, pp = 0060FE98 Inside function, *pp = 00000000 After: 00000000 */

在 C/C++ 中,*ptr++是一个非常经典且高频使用的表达式。它的核心逻辑可以总结为一句话:先取当前指针指向的值,然后将指针向后移动一个单位。

为了让你彻底弄懂,我们从底层原理到实际代码进行拆解:

1. 底层原理:运算符优先级与结合性

在这个表达式中,同时出现了*(解引用)和++(后置自增)。
根据 C/C++ 的语法规则:

  • 后置++的优先级高于*
  • 当优先级相同时,结合方向是从右向左。

因此,*ptr++在编译器眼中等价于*(ptr++)

2. 具体执行步骤

假设ptr是一个指向数组的指针,*(ptr++)的执行过程分为两步:

  1. 取值:先对当前的ptr进行解引用,获取它当前指向的内存中的值。
  2. 移动指针:随后,ptr自身的地址发生偏移,指向下一个元素(步长取决于指针的类型,例如int*会向后移动 4 个字节)。

⚠️ 核心注意点:这个表达式只改变了ptr的指向,并没有修改原来内存位置里的数据值。

3. 代码演示

我们来看一段直观的代码:

#include<stdio.h>intmain(){intarr[]={10,20,30};int*ptr=arr;// ptr 初始指向 arr[0]// 使用 *ptr++intval=*ptr++;printf("取出的值 val = %d\n",val);// 输出: 10printf("当前指向的值 *ptr = %d\n",*ptr);// 输出: 20return0;}

结果解析:val拿到了旧值10,而ptr已经悄悄向后移动,现在指向了20

4. 易混淆对比(避坑指南)

初学者经常把*ptr++和下面这两个表达式搞混,它们的区别非常大:

表达式等价形式作用对象结果
*ptr++*(ptr++)指针本身取出旧值,指针向后移动,数据不变
(*ptr)++(*ptr)++指向的数据取出旧值,数据加 1,指针不动
*++ptr*(++ptr)指针本身指针先向后移动,再取出新位置的值

💡 总结与应用

*ptr++这种“先取值,后移动”的特性,非常适合用来顺序遍历数组。在底层 C 语言开发中,它能让遍历数组的代码变得非常简洁优雅,不需要像arr[i++]那样单独写一行ptr++

http://www.jsqmd.com/news/1400344/

相关文章:

  • 如何使用Receptionist实现Swift分布式集群服务发现
  • DeepStream视频分割 pipeline:基于Portrait-Segmentation的多摄像头实时处理方案
  • Unity许可证验证绕过完整指南:用UniHacker快速解锁全平台开发
  • ncmdump 快速上手:3 关解锁网易云 NCM 文件转换
  • CDDIS 天顶总延迟(ZTD)数据下载教程
  • ComfyUI中文工作流快速上手指南:零基础玩转AI绘图不再难
  • 群星全DLC免费解锁实操:Stellaris DLC Unlocker 在 Windows 和 Linux 上的完整记录
  • 如何用Nail-Qwen3.6-35B-A3B-GGUF实现多轮对话?解锁262k tokens超长上下文能力
  • 掌握tumblr.js核心功能:用户信息、博客数据与内容发布全攻略
  • COSMO-RS 实操:从量子力学到热力学性质的“无参”预测之路
  • combo实战:5分钟快速上手模型组合,让你的分类器性能飙升
  • Ghidra逆向工程框架完全指南:从安装到实战,把“看不懂的二进制“变成“读得懂的代码“
  • 从Vim新手到高效开发者:一年Neovim实战配置与效率提升指南
  • C++输入输出、字符串分割
  • SOFARegistry集群部署教程:Docker Compose与Kubernetes方案
  • 30分钟上手Huginn:零基础打造自己的自动化工作流
  • PhotoGIMP实操指南:把免费GIMP 3改造成熟悉的Photoshop界面,告别高价订阅
  • 深入理解RAT-retrieval-augmented-thinking架构:ModelChain类与双客户端设计详解
  • 杭州黄金旧饰准备出手,聊聊老凤祥饰品回收相关注意事项 - 日常前沿快讯
  • 32B视觉语言模型如何塞进32GB显卡?RTX 5090上的INT8量化部署与显存优化全记录
  • 3 分钟告别 Photoshop 订阅:用 PhotoGIMP 把免费 GIMP 改造成熟悉的界面
  • 凌晨一点,你还在为几百条测试用例加班吗?GameAISDK把游戏AI测试变成日常
  • AI 推理服务经过 Service Mesh:怎样拆分延迟与算力成本
  • 如何在Django Admin中集成Django-ColorField:5分钟快速上手
  • 告别手动装软件:用 Homebrew 一条命令搞定 macOS 与 Linux 环境部署
  • 从评论学“行业中性”
  • Parsec虚拟显示驱动完整指南:无物理屏幕也能5分钟搞定多屏扩展
  • 告别建造受限:ValheimPlus 英灵神殿增强模组 3 步上手完整指南
  • 2026年廊坊消防验收专用防火涂料商贸公司梳理 三月春核心优势及行业选择参考 - 小范同学a
  • 深入理解 shriek-fx 核心组件:事件驱动架构如何简化复杂业务逻辑