C/C++中二级指针传递参数【个人遇到内存值发生改变现象的记录及相关修正方法】

news/2024/7/9 4:21:10

目录

0、前言

1、二级指针传参奇怪现象

2、分析

3、解决方法


0、前言

        在c/c++中,时常会使用到主调函数通过参数去获取被调函数中的数值情况。针对这种情况,我前面也写过C/C++主调函数从被调函数中获取(各种类型)数据内容方式的梳理归纳文章。但这篇文章中着重是写各基础数据类型的传递方式,如何传递一维数组值或者多维数组值得情况就没有涉及。那么在c/c++中,传递n维数值则需要通过n+1维的指针参数去传递。这篇文章就是去讲一下二级指针去传递数组值情况中发生的奇怪现象。需要了解详细的二级指针传参原理和过程可以去查看以下两篇文章:C语言参数传递(值传递、地址传递)+二级指针和使用二级指针传出参数。

1、二级指针传参奇怪现象

        项目需要,写了一个代码,运行后发现二级指针传参数值遇到打印会发生改变。抽象代码如下:

#include <stdio.h>

void f(int **y);//二级指针传参函数

int main()
{	
	int *kk = 0;
	f(&kk);
	printf("%d\n %d \n %d \n",kk[0],kk[1],kk[2]);
	getchar();
	return 0;
}
void f(int **y)
{
	int t[3]={6 , 7 ,10};//需要传出去数组的内容
	*y = t;
}

运行可以发现正确打印出需要的数值:

 然而在打印前面随意加个打印,再看打印数值就不对了:

        以上的现象着实让人难以理解,为此进行了一系列的分析。

2、分析

        根据调试和打印地址、内存值发现:

1)、f函数中添加printf(" %d \n %d \n %d \n", **y, *(* y + 1), *( * y + 2));//内部寻址获得的数值是正确的;

2)、在主函数中指针kk直接索引t数组:都在主调函数内,t的栈上内存不会消失,kk的寻址位置正确。

        最后定位到应该是调用f函数后获取被调函数f中t数组的值,将其内存地址赋给kk,运行完后局部变量t应该释放了。原因应该就是局部变量的释放导致了kk指向的内存数值发生变化。【这一块不理解的就是:f运行完理论内存值就不在了,为什么不加其他的打印,却能够正常打印?有知道的可以评论区说说】

3、解决方法

        根据问题的定位,进行相关的修改。发生以上问题的原因就是被调函数f中的数组t是局部变量,在函数f被调用运行完后,t变量定义在栈上的内存将被释放。打印内存数据将会导致打印内容错误。

        为此进行修改,即将其中需要传递值得数组进行全局定义。或者直接在堆上创建内存,然后再进行值的拷贝或者传递(该部分就是需要记得手动释放内存,不是很推荐)

1)、全局直接定义数组,被调函数中赋值

 2)、static指定数组指向全局变量所在空间

 


http://lihuaxi.xjx100.cn/news/598428.html

相关文章

实战干货|自研数据存储迁移MySQL实战

背景 最近公司内部在做某自研数据存储的下线工作&#xff0c;这里我们暂且化名其为DistributeSQL&#xff0c;由于DistributeSQL不再进行服务支持&#xff0c;需要迁移项目中使用到该存储到其他数据存储中。 本篇来聊聊这次在数据存储迁移过程中的方案设计思路、实现的大致细节…

1.8米的床床垫尺寸是多少

1.8米床垫是指床垫的宽度,在1.8床垫中,长度尺寸通常有这几种,即:1.9米,2米,2.1米等。通常来说,最适合的床垫尺寸应该按照家庭成员的身高而定。一般床垫要比使用者的身高长20厘米,这样才能让人体自由舒展,不会在睡觉的时候感到拥挤。此外,适用于双人床的床垫尺寸有这几…

(4)go-micro微服务proto开发

目录一 Protobuf介绍二 安装Protobuf三 Protobuf语法1.1 基本规范1.2 字段规则1.3 service如何定义1.4 Message如何定义四 proto代码编写五 生成.go文件六 最后 一 Protobuf介绍 Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使…

一篇文章彻底弄懂 Java 反射的使用

文章引用自:一篇文章彻底弄懂 Java 反射的使用 原文链接:https://zhuanlan.zhihu.com/p/378412723 说到Java反射,必须先把 Java 的字节码搞明白了,也就是 Class , 大 Class 在之前的文章中,我们知道了Java的大Class就是类的字节码,就是一个普通的类,里面保存的是类的信息…

嵌入式Linux-对子进程的监控

1. 进程的诞生与终止 1.1 进程的诞生 一个进程可以通过 fork()或 vfork()等系统调用创建一个子进程&#xff0c;一个新的进程就此诞生&#xff01;事实上&#xff0c;Linux系统下的所有进程都是由其父进程创建而来&#xff0c;譬如在 shell 终端通过命令的方式执行一个程序./…

参加《2022 中国开发者影响力盛典》我的 4 重收获!

感谢 CSDN 邀请&#xff0c;西红柿有幸参加了 2022 中国开发者影响力盛典暨 CSDN 企业生态汇&#xff0c;让我有了一个不虚此行的下午&#xff0c;也跟大家分享一下我在会上的 4 重收获吧~第一重收获&#xff1a;互联网圈大佬 会议聚焦开发者生态建设主题&#xff0c;分享了 CS…

【数据结构与算法】 | 用队列实现栈

用队列实现栈 链接&#xff1a; https://leetcode.cn/problems/implement-stack-using-queues/ 1. 要求 2. 思路 栈的性质是先进后出&#xff0c;队列的性质是先进先出。 题目要求是用两个队列来完成栈的实现&#xff0c;那么大思路就是通过倒腾数据来完成。 3. 代码实现…

AtCoder Beginner Conest 284 解题报告

AtCoder Beginner Conest 284 解题报告(A~G)AtCoder Beginner Conest 284 解题报告 \(\text{By DaiRuiChen007}\) \(\text{Contest Link}\) A. Sequence of Strings 模拟,时间复杂度 \(\Theta(n)\) #include<bits/stdc++.h> using namespace std;signed main() {int n…