指针作为形参和返回值的区别

关于指作为针形参与返回值的常见问题

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

posted @   jixhua  阅读(1807)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示