工作中优化一段代码,代码中有一大段分配堆内存的内容,我觉得这段代码太长了,更适合放在子函数里面。

我把指针作为参数,然后在子函数中malloc分配内存,结果出现了问题,函数结束后,以参数传进来的指针并没有指向分配的内存。

比如说:

int fun(unsigned char *p, unsigned char **p1) {
p = (unsigned char *)malloc(N * sizeof(unsigned char));
if (NULL == p)
return -;
// 给二维指针p1分配
p1 = fun_set_p1();
if (NULL == p1) {
free(p);
return -;
}
return ;
} unsigned char *p;
unsigned char **p1
fun(p, p1);

运行完fun后,*p和**p1并没有发生变化。

指针作为参数不是传的是地址吗?怎么没变化呢?

其实这样想是一种误区,其实指针作为参数也是值传递,在函数中将参数复制一份而已。指向的是同一块内存地址。假设参数传的是int *p,函数内copy的j是int *p_1。在函数中操作*p_1,例如*p_1 = 1, 则p_1所指向的内容就变成了1.,由于他们是指向同一块地址,所以即使他们不是同一个指针*p所指向的内存也会被改变。

但如果让p_1指向其他的内存地址,则由于是值传递,p并不会因此而改变。

其实反汇编可以看出,参数的传递其实就是将变量放入新开辟的函数栈空间,也就是我说的“copy一份”,函数中再对栈空间里的内容操作,这就是值传递的本质。

所以这种情况该怎么办呢?

一种情况是函数 返回 指向新申请内存的指针

unsigned char* fun() {
unsigned char* p = malloc(N * sizeof(unsigned char));
return p;
}

但如果你需要设置多个指针就不合适了。

另一种办法就是使用二级指针、三级指针。

int fun(unsigned char **p, unsigned char ***p1) {
*p = (unsigned char *)malloc(N * sizeof(unsigned char));
if (NULL == *p)
return -;
// 给二维指针p1分配
*p1 = fun_set_p1();
if (NULL == *p1) {
free(*p);
return -;
}
return ;
} unsigned char* p;
unsigned char** p1;
fun(&p, &p1);

其实就是指向指针的指针。

函数内值传递,拷贝一份,其指向的内存的内容改变了,参数指向的内存的内容就跟着变了。

子函数内malloc分配内存,论如何改变指针参数所指内存,二级指针、三级指针的应用的更多相关文章

  1. C++ 数组长度 以及 数组名作为参数传递给函数 以及 为什么不在子函数中求数组长度

    在看排序,首先是插入排序,思路理清后想用代码实现,然后问题来了: 如何求数组长度? 如果没记错,在Java中应该是有直接可用的方法的, Python中(序列)也有.len,在C/C++中,字符串倒是有 ...

  2. 【c++】指针参数是如何传递内存的

    [c++]指针参数是如何传递内存的   如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *) ...

  3. 【转】【c++】指针参数是如何传递内存的

    参数策略 如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(c ...

  4. c++指针参数是如何传递内存的

    参数策略 如果函数的参数是一个指针,不要指望用该指针去动态申请内存.如下: void GetMemory(char *p, int num) { p = (char *)malloc(sizeof(c ...

  5. 【转】【C/C++】内存分配函数:malloc,calloc,realloc,_alloca

    转自:http://www.cnblogs.com/particle/archive/2012/09/01/2667034.html#commentform malloc: 原型:extern voi ...

  6. c malloc分配内存

    php中的内存分配有用类似emalloc这样的函数,emalloc实际上是C语言中的malloc的一层封装,php启动后,会向OS申请一块内存,可以理解为内存池,以后的php分配内存都是在这块内存池中 ...

  7. <转载>内存管理内幕-动态分配的选择、折衷和实现 对malloc内存分配有个简单的描述,对内存管理有个大致的说明

    这篇文章看后感觉不错,和我在glibc下的hurdmalloc.c文件里关于malloc的实现基本意思相同,同时,这篇文章还介绍了一些内存管理方面的知识,值得推荐. 原文链接地址为:http://ww ...

  8. C++ 内存、new与malloc分配内存区别?

    一关于内存 1.内存分配方式 内存分配方式有三种: (1)从静态存储区域分配.内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.例如全局变量,static变量. (2)在栈上创建. ...

  9. 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型

    小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...

随机推荐

  1. mybatis结合log4j打印SQL日志

    mybatis结合log4j打印SQL日志 1.Maven引用jar包 默认的mybatis不能打印出SQL日志,不便于查看调试,须要结合log4jdbc-log4j2就能够完整的输入SQL的调试信息 ...

  2. numpy tricks(二)—— 删除多维数组的行或列

    numpy.delete numpy 下的多维数组,如果要删除其中的某些行,或某些列,不可以用置空的方式,进行设置: A[1, :] = None, ⇒ 会将 A 中的第一行数据全部置为 Nan 1. ...

  3. WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush)

    原文:WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush) 前面我们提到了LinearGradientBrush可以用来画渐变填充图,那么我们同时也可以使用ImageBr ...

  4. 关于JDBC连接数据库时出现的Public Key Retrieval is not allowed错误

    问题描述 最近在学习MyBatis框架,参考官方的文档通过配置文件的方式已经实现了通过Configuration配置文件和mapper映射文件访问mysql8数据库,于是想试试不使用XML文件去构建S ...

  5. WPF 拼音输入法

    原文:WPF 拼音输入法 本文来告诉大家如何使用 WPF 来写一个输入法,使用的方式是钩子. 目录 键盘 解析键盘 获得按键 输入流向 算法 实际上本文是在使用一个好用的软件 希沃白板 的时候发现在里 ...

  6. PAT 1001-1010 题解

    早期部分代码用 Java 实现.由于 PAT 虽然支持各种语言,但只有 C/C++标程来限定时间,许多题目用 Java 读入数据就已经超时,后来转投 C/C++.浏览全部代码:请戳 本文谨代表个人思路 ...

  7. ASP.NET获取web应用程序的路径

    服务器磁盘上的物理路径: HttPRuntime.AppDomainAppPath虚拟程序路径: HttpRuntime.AppDomainAppVirtualPath 任何于Request/Http ...

  8. OpenSSL 使用 base64 编码/解码(liang19890820)

    关于 OpenSSL 的介绍及安装请参见:Windows 下编译 OpenSSL 下面主要介绍有关 OpenSSL 使用 base64 编码/解码. 简述 编码解码 更多参考 编码/解码 #inclu ...

  9. Efficient store queue architecture

    One embodiment of the present invention provides a store queue that applies the stores to a memory s ...

  10. OpenCV中基于HOG特征的行人检测

    目前基于机器学习方法的行人检测的主流特征描述子之一是HOG(Histogram of Oriented Gradient, 方向梯度直方图).HOG特征是用于目标检测的特征描述子,它通过计算和统计图像 ...