zoukankan      html  css  js  c++  java
  • 指针参数是如何传递内存的?

           如果函数的参数是一个指针,不要指望用该指针去申请动态内存。示例7-4-1中,Test数的语句GetMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL,为什么?

    void GetMemory(char *p, int num)
    {
        p = (char *)malloc(sizeof(char) * num);
    }
    void Test(void)
    {
        char *str = NULL;
        GetMemory(str, 100);    // str 仍然为 NULL    
        strcpy(str, "hello");    // 运行错误
    }

    示例7-4-1 试图用指针参数申请动态内存

    毛病出在函数GetMemory中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。

    =============================================================================================================================

    如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,见示例7-4-2

     

    void GetMemory2(char **p, int num)
    {
        *p = (char *)malloc(sizeof(char) * num);
    }
    void Test2(void)
    {
        char *str = NULL;
        GetMemory2(&str, 100);    // 注意参数是 &str,而不是str
        strcpy(str, "hello");    
        cout<< str << endl;
        free(str);    
            str = NULL;

    }

    示例7-4-2用指向指针的指针申请动态内存

     

    由于“指向指针的指针”这个概念不容易理解,我们可以用函数返回值来传递动态内存。这种方法更加简单,见示例7-4-3

    char *GetMemory3(int num)
    {
        char *p = (char *)malloc(sizeof(char) * num);
        return p;
    }
    void Test3(void)
    {
        char *str = NULL;
        str = GetMemory3(100);    
        strcpy(str, "hello");
        cout<< str << endl;
        free(str);    
            str = NULL;
    }

    示例7-4-3 用函数返回值来传递动态内存

    用函数返回值来传递动态内存这种方法虽然好用,但是常常有人把return语句用错了。这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例7-4-4

    char *GetString(void)
    {
        char p[] = "hello world";
        return p;    // 编译器将提出警告
    }
    void Test4(void)
    {
    char *str = NULL;
    str = GetString();    // str 的内容是垃圾
    cout<< str << endl;
    }

    示例7-4-4 return语句返回指向“栈内存”的指针

    用调试器逐步跟踪Test4,发现执行str = GetString语句后str不再是NULL指针,但是str的内容不是hello world而是垃圾。

    如果把示例7-4-4改写成示例7-4-5,会怎么样?

    char *GetString2(void)
    {
        char *p = "hello world";
        return p;
    }
    void Test5(void)
    {
        char *str = NULL;
        str = GetString2();
        cout<< str << endl;
    }

    示例7-4-5 return语句返回常量字符串

    函数Test5运行虽然不会出错,但是函数GetString2的设计概念却是错误的。因为GetString2内的“hello world”是常量字符串,位于静态存储区,它在程序生命期内恒定不变。无论什么时候调用GetString2,它返回的始终是同一个“只读”的内存块。

     



  • 相关阅读:
    使用 Spring data redis 结合 Spring cache 缓存数据配置
    Spring Web Flow 笔记
    Linux 定时实行一次任务命令
    css js 优化工具
    arch Failed to load module "intel"
    go 冒泡排序
    go (break goto continue)
    VirtualBox,Kernel driver not installed (rc=-1908)
    go运算符
    go iota
  • 原文地址:https://www.cnblogs.com/XiHua/p/3807862.html
Copyright © 2011-2022 走看看