zoukankan      html  css  js  c++  java
  • 指针参数在内存中的传递

    代码一

    View Code
    void GetMemory(char *p , int num)
    { 
        p = (char *)malloc(sizeof(char) *num);
    }
    
    int main()
    { 
        char *str = NULL;
        GetMemory(str,100); //str 还是 NULL
        strcpy(str,"hello"); //运行出错
    }

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

    代码二

    View Code
    void GetMemory(char **p, int num)
    {
        *p = (char *)malloc(sizeof(char) * num);
    }
    
    int main()
    {
        char *str = NULL;
        GetMemory(&str,100); //看清传入的参数
        strcpy(str,"hello");
        prinf("%s",str); //顺利输出
        free(str);  //记得释放内存
    }

    对于理解“指向指针的指针”概念困难的同学,可以用函数返回值来传递内存。但是我似乎没有看出这种方法比代码而简单多少。

    代码三

    View Code
    char* GetMemory(int num)
    {
        char *p = (char *)malloc(sizeof(char) * num);
        return p;
    }
    
    int main()
    {
        char *str = NULL;
        str = GetMemory(100);
        strcpy(str,"hello");
        printf("%s",str);
        free(str); //记得释放内存呀
    }

    在写函数返回值来传递内存时,有人会不小心把return语句写错。比如返回“栈内存”的指针。(用人话讲 就是返回一个 在函数体内的局部变量,之所以不能这么干是因为函数执行结束时,这些局部变量所存储的空间会被释放)比如你不能这么写:

    代码四

    View Code
     1 char* GetString(void)
     2 {
     3     char p[] = "hello world";
     4     return p; 
     5 }
     6 
     7 int main()
     8 {
     9     char *str = NULL;
    10     str = GetString();
    11     strcpy(str,"hello");
    12     printf("%s",str);
    13 }

    运行出来会打印出奇怪的东西,反正不是我们要的结果。编译的时候第4行会有警告,function returns address of local variable(函数返回了一个局部变量的地址) 。调试会发现执行str = GetString()后str不是NULL指针,也不是“hello world”。如果改成下面这段代码呢?

    代码五

    View Code
    char* GetString(void)
    {
        char *p = "hello world";
        return p;
    }
    
    int main()
    {
        char *str = NULL;
        str = GetString();
        printf("%s",str);
    }

    运行是可以的,但是这么写代码是有问题的,GetString函数里面的“hello world”是一个常量字符串,位于静态存储区域,它在程序生命期间恒定不变,无论什么时候调用这个函数,它返回的都是“hello world”。

    最后整理 如何预防野指针

    “野指针”不是NULL指针,是指向“垃圾”内存的指针。人们一般不会错用NULL指针,因为用if语句很容易判断。但是“野指针”是很危险的,if语句对它不起作用。
     
    (1)指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。例如
    char *p = NULL;
    char *str = (char *) malloc(100);
     
    (2)指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。
    (3)指针操作超越了变量的作用范围。这种情况让人防不胜防。
  • 相关阅读:
    JAVA中的流-简介(二)
    JAVA中的流-简介(一)
    Java中内部类简介
    应用小练习-自定义栈
    集合知识点(二)
    集合知识点(一)
    JAVA中的正则表达式简介
    从头文件中学习sfr和sbit
    PCB中实现元器件旋转一个角度放置
    DXP中插入LOGO字体方法(2)
  • 原文地址:https://www.cnblogs.com/ligongzi/p/2659986.html
Copyright © 2011-2022 走看看