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


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

    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
    ", *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
    ", *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
    ", *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
    ", *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
    ", *p);    // 100
    
        // free :堆区空间需要手动释放
        if (p != NULL) {
            free(p);
            p = NULL;
        }
        
        return 0;
    }

    和第3的区别在于不是通过形参给变量赋值,而是直接返回了指针变量,注意:这里返回的不是栈区的局部变量地址(第1),而是堆区的地址,堆区变量是不会自动释放的,所以返回是合法的。

    指针指向同图4

  • 相关阅读:
    Python中的生成器
    API测试的五大好处
    Python可变参数*args和**kwargs
    Python中的迭代器
    docker下php安装imagick扩展
    docker端口映射不生效
    mysql学习笔记(一)一条sql查询语句是如何执行的
    lavavel学习笔记(一)安装
    mysql学习笔记(四)索引
    mysql学习笔记(二)一条sql更新语句是如何执行的
  • 原文地址:https://www.cnblogs.com/jixiaohua/p/11349112.html
Copyright © 2020-2023  润新知