深入理解C语言中两级指针(char **pptr)的参数的用法

最近在看亚嵌的《Linux C编程一站式学习》,对其中的两层指针的参数用法有些疑惑,下面和大家分享一下学习心得!


首先来看一段代码:

 
  
 
  

/* main.c */
#include 
#include 

static const char *msgg[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

void get_w_day(const char **pp)
{
     pp[0] = msgg[2]; // *pp     = msgg[0];
     pp[1] = msgg[3]; // *(pp+1) = msgg[1];
}

int main(void)
{
          char  ptr[2] = {};
    const char  *pptr = ptr;    //这里初始化也可以为NULL,不会导致编译出错和运行时的段错误,但在实际程序中最好详细初始化
    const char **ppptr = &pptr; //在ppptr参数传入get_w_day()函数之前,必须对其进行初始化,否则会导致运行时的段错误
 				//仔细想一下原因,如果ppptr是NULL,那么get_w_day()函数修改的*ppptr就会修改一个不确定的位置
                                //进一步从底层查找原因,如果ppptr是NULL,那么传入get_w_day()时刻的实际值就是0x0,也就是我们要操作*((char*)0x00) = ??
                                //这样必然导致一个段错误
    get_w_day(ppptr);
    
    char fuck      = **ppptr + 1;     //这里的fuck应该等于几? 答案是'U' ==> 'T'+1  
    char fuckk     = *(*ppptr + 1);   //如果是 fuck = *(*ppptr + 1) 呢? 答案是 'u' ==> 指向"Tuesday"头指针加1
    char fuckkk    = **(ppptr + 1);   //如果是  **(ppptr + 1)呢?答案是'V'
    char fuckkkk   = **((ppptr+1) + 1 //是'W' ==> 'V'+1
    char fuckkkkk  = **((ppptr+2) + 1 //是一个不确定的值,有可能引起段错误
    printf("%s\t%s\n", *ppptr, *(ppptr+1));  
    return 0;
}


指针就是指向内存地址的变量,二级指针也是指针,即指向指针的指针,同样可以表示传入参数、传出参数或者Value-result参数,只不过该参数所指的内存空间应该解释成一个指针变量。

这里有一个法则,传入一个N级的指针,就可以修改N-1级的指针,原因是C语言的参数传递是按值传递的,直接修改形参是无法改变实参的,但可以通过传入的指针参数修改其指向的的内容,N级指针指向的内容就是一个N-1级的指针,边界情况就是参数是一个非指针类型的变量,可以理解为0级指针,这样就修改不了其内容。

对于上述代码,可以在gei_w_day()函数中,修改一级指针的内容,即可以修改×ppptr的值,而*ppptr 对应 pptr,这里把他看成一个字符串数组名,从而可以理解为可以在gei_w_day()函数中改变字符串数组中的0项、1项...的值。

        在来看看形参中const的作用,如下代码所示,

char ** p1;        // int元素不可修改
char * const * p2; // int *一级指针不可修改
char ** const p3;  // int **二级指针不可修改

思考题:

 
  

//思考题:如果将下述代码做改动,那么 printf("%s\t%s\n", *ppptr, *(ppptr+2)); 能否打印出
void get_w_day(const char **pp)
{
     pp[0] = msgg[2]; 
     pp[1] = msgg[3];
     pp[2] = msgg[4]; //新增...
}




你可能感兴趣的:(C语言)