C語言中的三級指針,理解著實費一番功夫

先來貼一段代碼,這段代碼很多人可能也遇到過,而且也囊括了三級指針的所有內容

#include

char *c[ ] = { "ENTER" , "NEW" , "POINT" , "FIRST"};

char **cp[ ] = { c+3 , c+2 , c+1 , c };

char ***cpp = cp;

main ( )

{

printf ( "%s#" , **++cpp );

printf ( "%s#" , *--*++cpp);

printf ( "%s#" , *cpp[-2]+3);

printf ( "%s#" , cpp[ -1] [ -1] + 1 );

}

char *c[ ] = { "ENTER" , "NEW" , "POINT" , "FIRST" };

這個肯定能理解,就是定義幾個字符串,然後將其放入一個數組中,因為數組內放的是字符串,所以數組類型必須為char*。

我們在定義一個字符串的時候,經常是這麼寫char* str = "hello world";

那麼我們要定義多個字符串的時候,就可以利用數組了,像上邊那樣。

char **cp[ ] = { c+3 , c+2 , c+1 , c };

這是二重指針。因為前邊定義的c是數組類型,也就是一種常量指針(地址),所以c+3,c+2,c+1,c都是指向數組c每個元素的地址。現在要將數組元素的地址放在數組中,那麼該用什麼數據類型呢?存放一個變量(也可以是字符串)地址時,需要的是指針,那麼存放一個地址的地址,就需要一個二重指針(因為只有指針可以存放地址,這裡是存放一個地址的地址,所以要用二重指針)。

char ***cpp = cp;

cp本來就是一個常量指針,再加上他的類型是char**,所以它就是一個三級指針。這裡cpp的類型是char***,也是三級指針,所以將cp直接賦值給cpp也就沒有問題啦(類型相同的嘛(都是三級指針))。

printf ( "%s#" , **++cpp );

++的優先級高,所以先執行++cpp,也就是得到數組cp的第二個元素地址。

兩個**我們分開看,先看*++cpp,這是取得數組cp第二個元素的值c+2。也就是說 *(地址)就指向了該地址所存儲的內容(該內容為一個變量或另一個變量的地址(即指針),或為存放一個變量地址的地址(指針的指針)…..)

在看**++cpp,相當於*(c + 2),所以這裡得到的是數組c第三個元素的首地址,也就是"POINT"字符串的首地址,所以這裡輸出POINT# ,並且,該語句執行後導致cpp當前的指向發生了變化。

printf ( "%s#" , *--*++cpp );

由優先級和執行順序的關係得知,這裡會先執行++cpp,因為前一個輸出語句已經導致cpp加1了,所以現在cpp再加1,那麼會得到數組cp的第三個元素地址,即++cpp指向cp+2。再執行*++cpp,這時取得數組cp第三個元素的值c+1。

然後再執行--*++cpp,相當於--(c+1),也就是c,然後再執行*c,所以取得是數組c的第一個元素的首地址,所以輸出結果為ENTER# 。該語句執行後同樣會導致cpp當前的指向發生變化。

printf ( "%s#" , *cpp[-2] + 3 );

數組下標優先,所以會先執行cpp[-2],也就是*(cpp-2);因為前兩輸出語句導致cpp加了2,所以現在-2後,又使cpp-2的地址為數組cp的首地址,所以得到數組cp第一個元素c+3。再執行*(cpp[-2]),也就是*(c+3),這就得到了數組c的第四個元素的首地址,也就是字符串"FIRST"的首地址,然後這個地址再加3,所以得到字符串ST的首地址,因此輸出結果為ST# 。該語句執行後cpp當前的指向未發生變化。

printf ( "%s#" , cpp[ -1 ] [ -1 ] + 1 );

先執行cpp[-1],相當於*(cpp-1)。因為前面兩個輸出語句導致cpp被加了2,它目前指向數組cp的第三個元素,所以cpp-1相當於數組cp第二個元素c+2,然後再執行cpp[-1][-1],相當於(c+2)[-1],也就是*(c+2-1) = *(c+1),所以得到數組c的第二個元素的首地址,也就是字符串"NEW"的首地址,然後在這個地址上加1,就得到字符串EW的首地址,所以輸出結果為EW# 。該語句執行後cpp當前的指向同樣未發生變化。


分享到:


相關文章: