• 指针用作传出参数时,需要二级指针


    要点:

    1. 参数传递的原则是:形参传给实参,不能反向传递;

    2. 一级指针可以在函数内部修改形参指针指向的内容;

    如:

    void fun(char *p) 
    { 
        p[2] = a;//由形参(实参)指向的函数外部的数组的内容就被改变了。
    } 

    如果我们想改变实参本身呢?也就是说,我们连指针值都要改变,如果使用:

    void GetMemory(int num, char *p) 
    { 
        p = (char *)malloc(num * sizeof(char))
        //或C++中:p = new char[10];
    } 

    就不行了,因为在函数内部不能通过改变形参的值来改变实参


    但是,可以通过二级指针来改变指针值。

    void GetMemory(char **p, int num)
    { 
        *p = new char[num]; 
        *p[2] = a; 
        delete char[];
    } 


    关键是:

    1. 编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。

    在本例中,_p申请了新的内存,只是把 _p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。
    如果非得要用指针参数去申请内存,那么应该改用“指向指针的指针”,
    2. 变量作函数形参调用的时候都是要分配一个副本,不管是传值还是传址。传入后就和形参没有关系了,它不会改变形参的值。


    注意指针所指向的内存是在函数内分配的还是在函数外分配的,以及是不是在堆上分配的。

    你定义了一个指针,但是并没有分配指针指向对象所需的内存空间;当函数返回后,此函数栈中的内存会被释放掉,不要让指针指向此函数栈中的内存空间,要指向堆上或此函数外的内存空间。


    代码范例:

    #include <stdio.h>
    #include <string.h>
    
    char *f_void(void);
    void f_1ptr(char *ret);
    void f_1ptr_o(char *ret);
    void f_2ptr(char **ret);
      
    int main()
    {
        char havec[] = "this is abcdefghijklmnopqrstuvwxyz";
        char *tmp;  // Alloc memory for single indirection pointer
        char **ret; // Alloc memory for double indirection pointer
    
        ret = &tmp; // this is important, why?
    
        tmp = f_void();
        printf("f_void():%s\n",tmp); // Ok
    
        printf("Before calling f_1ptr():havec = %s.\n",havec);
        f_1ptr(havec);
        printf("After calling f_1ptr():havec = %s.\n\n",havec);
     
        printf("Now try to output argument using single indirection pointer!\n");
    	f_1ptr_o(tmp);
    	printf("The output result is:%s", tmp);
        f_2ptr(ret);
        printf("%s\n",tmp); // Ok
     
        return 0;
    }
     
    char *f_void(void) // return a pointer, memory is alloced in global
    {
        return "This function has no parameters.\n";
    }
    
    void f_1ptr(char *ret)
    {
        char *tmp;
    	
        printf("Search for the 1st 'f' character in '%s'.\n", ret);
        if((tmp = index(ret,'f')) ==NULL) // this is just a example
            return ;
        *(tmp+1) = '\0';
    }
    
    void f_1ptr_o(char *ret) // Try to output argument using single indirection pointer
    {
        char *t8;
    
        static char aa[] = "Output argument test!\n"; // 该处的static指定数组aa[]指向全局变量所在空间
    	t8 = ret;
    	// ret = aa;
    	memcpy(t8, aa, sizeof(aa));
    }
    
    void f_2ptr(char **ret) // output argument using double indirection pointer
    {
        static char aa[] = "Output argument test!\n"; // 该处的static指定数组aa[]指向全局变量所在空间
        *ret = aa;
    }

    运行结果:
    $ ./pointer2nd-test.exe
    f_void():This function has no parameters.
    
    Before calling f_1ptr():havec = this is abcdefghijklmnopqrstuvwxyz.
    Search for the 1st 'f' character in 'this is abcdefghijklmnopqrstuvwxyz'.
    After calling f_1ptr():havec = this is abcdef.
    
    Now try to output argument using single indirection pointer!
    The output result is:Output argument test!
    Output argument test!
    
    

    
    


  • 相关阅读:
    CDQ分治
    [noip模拟赛2017.7.15]
    [noip模拟赛2017.7.11]
    [noip模拟赛2017.7.10]
    [noip模拟赛2017.7.7]
    [noip模拟赛2017.7.6]
    [noip模拟赛2017.7.4]
    回文检测
    mapreduce引用第三方jar
    Spark安装和配置
  • 原文地址:https://www.cnblogs.com/java20130726/p/3218624.html
Copyright © 2020-2023  润新知