深入理解C語言中兩級指標(char **pptr)的引數的用法
阿新 • • 發佈:2019-01-24
最近在看亞嵌的《Linux C程式設計一站式學習》,對其中的兩層指標的引數用法有些疑惑,下面和大家分享一下學習心得!
首先來看一段程式碼:
/* main.c */ #include <stdio.h> #include <stdlib.h> 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]; //新增... }