关于指作为针形参与返回值的常见问题
1、返回栈中局部变量的地址
#include <stdio.h> int *fun(){ int a = 10; // a为当前方法栈中的局部变量,结束即释放 return &a; // 所以传递出去的会是一个无效(非法)地址 } int main(int argc, char const *argv[]) { int *a = NULL; a = fun(); *a = 100; // error,操作非法内存 printf("a = %d\n", *a); return 0; }
2、返回data区的地址
代码同上,不同之处在于a加个static,变为静态局部变量,等同于全局变量
#include <stdio.h> int *fun(){ static int a = 10; // 静态局部变量,不会随着方法栈自动释放 return &a; // 返回的是有效地址 } int main(int argc, char const *argv[]) { int *a = NULL; a = fun(); *a = 100; // ok printf("a = %d\n", *a); return 0; }
3、指针作为形参传递(一)
#include <stdio.h> #include <stdlib.h> void fun(int *tmp){ tmp = (int *)malloc(sizeof(int)); // 形参局部指针变量只在当前方法栈中有效 *tmp = 100; // 当前栈中tmp动态分配的内存未释放,造成内存泄漏 } int main(int argc, char const *argv[]) { int *p = NULL; fun(p); // p是空指针,没有指向,把p的值传给tmp printf("*p = %d\n", *p); // error 操作空指针所指向的内存 return 0; }
此时fun()函数和main()函数同级,tmp作为fun中的形参局部变量,对其操作不会影响main中的实参p;
并且给tmp在堆中动态分配内存,但是tmp随着fun方法栈的释放而消失,堆中的内存没有释放,造成内存泄漏。
4、指针作为形参传递(二)
#include <stdio.h> #include <stdlib.h> void fun(int *tmp){ *tmp = 100; } int main(int argc, char const *argv[]) { int *p = NULL; p = (int *)malloc(sizeof(int)); fun(p); // 值传递 printf("*p = %d\n", *p); // 100 return 0; }
此时在fun()函数中操作的不是指针变量tmp,而是tmp所指向的堆内存(没有改形参本身),也就是fun()方法栈中和main()方法栈中的两个变量tmp和p指向了同一块堆内存,fun()方法栈的释放并不会影响操作结果
5、指针作为返回值
#include <stdio.h> #include <stdlib.h> int * fun(){ int *tmp = NULL; tmp = (int *)malloc(sizeof(int)); // 在堆中分配内存 *tmp = 100; // 堆内存赋值 return tmp; // 返回堆区地址,函数调用完毕不释放 } int main(int argc, char const *argv[]) { int *p = NULL; p = fun(p); printf("*p = %d\n", *p); // 100 // free :堆区空间需要手动释放 if (p != NULL) { free(p); p = NULL; } return 0; }
和第3的区别在于不是通过形参给变量赋值,而是直接返回了指针变量,注意:这里返回的不是栈区的局部变量地址(第1),而是堆区的地址,堆区变量是不会自动释放的,所以返回是合法的。
指针指向同图4
原文地址:https://www.cnblogs.com/jixiaohua/p/11349112.html
时间: 2024-10-21 14:20:40