複雜指標宣告具體例項
左右宣告法則:
首先從最裡面的圓括號(未定義的識別符號)看起,然後往右看,再往左看。每當遇到圓括號時,就應該掉轉閱讀方向。一旦解析完圓括號裡面所有的東西,就跳出圓括號。重複這個過程直到整個宣告
修正:
筆者要對這個法則進行一個小小的修正,應該是從未定義的識別符號開始閱讀,而不是從括號讀起,之所以是未定義的識別符號,是因為一個聲明裡面可能有多個識別符號,但未定義的識別符號只會有一個。
連結:https://www.cnblogs.com/Lunais/p/5969181.html
int (*func)(int *p);
首先找到那個未定義的識別符號,就是func,它的外面有一對圓括號,而且左邊是一個*號,這說明func是一個指標,然後跳出這個圓括號,先看
右邊,也是一個圓括號,這說明(*func)是一個函式,而func是一個指向這類函式的指標,就是一個函式指標,這類函式具有int*型別的形參,返回值型別是 int。
#include <stdio.h>
int max( int *p )
{
return 0;
}int main ()
{
int *k;
int (*func)(int *p) = &max;
func( k );return 0;
}
int (*func)(int *p, int (*f)(int*));
func被一對括號包含,且左邊有一個*號,說明func是一個指標,跳出括號,右邊也有個括號,那麼func是一個指向函式的指標,這類函式具有int *和int (*)(int*)這樣的形參,返回值為
int型別。再來看一看func的形參int (*f)(int*),類似前面的解釋,f也是一個函式指標,指向的函式具有int*型別的形參,返回值為int。
#include <stdio.h>
int max( int *p )
{
return 0;
}int test( int *pt, int (*f)(int*))
{
return 0;
}int main ()
{
int *k;
int (*func)(int *p, int (*f)(int*)) = &test;
func( k, &max);return 0;
}
int (*(*func)(int *p))[5];
func是一個函式指標,這類函式具有int*型別的形參,返回值是指向陣列的指標,所指向的陣列的元素是具有5個int元素的陣列。
#include <stdio.h>
typedef int(*TYPE)[5];
TYPE fun( int *k )
{
int a[5];
TYPE p=&a;
return p;
}int main ()
{
//func是一個函式指標,這類函式具有int*型別的形參,返回值是指向陣列的指標
//所指向的陣列的元素是具有5個int元素的陣列。
int (*(*func)(int *p))[5] ;
func = &fun;
return 0;
}
int (*func[5])(int *p);
func右邊是一個[]運算子,說明func是一個具有5個元素的陣列,func的左邊有一個*,說明func的元素是指標,要注意這裡的*不是修飾 func的,而是修飾func[5]的,原因是[]運算子優先順序
比*高,func先跟[]結合,因此*修飾的是func[5]。跳出這個括號,看右邊,也是一對圓括號,說明func陣列的元素是函式型別的指標,它所指向的函式具有int*型別的形參,返回值型別為
#include <stdio.h>
int max( int *p )
{
return 0;
}int main ()
{
int (*func[5])(int *p);
func[0] = &max;return 0;
}
double (* (* P1)[10] )( double k );//陣列指標,第一個*說明陣列中包含的是指標,往右是引數列表,說明陣列中包含的是函式指標,這些函式沒有引數,返回值型別是double
#include <stdio.h>
/* "*(*P2[10])()"用typedef分解及使用 */
typedef double ( * ppt )( double k );
typedef ppt (*p)[2];double M( double k )
{
return k;
}double L( double k )
{
return k + 1;
}int main ()
{
double (*mm)(double k);
p a;
ppt arry[2] = { &M, &L };
a = &arry ;
mm = **a;//得到&M地址
mm = *(*a+1) ;//得到&L的地址
printf( "%f\n", mm(3.14));getchar();
return 0;
}
最後看一個比較難點的例子:double ( *(* (*fp3)( double(*u)(double k) ) )[1] )( double k );
對比:double (* (* P1) [1] )( double (*p) ( double k ) );
/*分析 double (* (* P1)[1] )( double (*p) ( double k ) ) :用左右法分析 :首先找到未知變數P1,往右看到第一個括號,往左看遇到第一個*,說明P1是一個指標。跳出第一個內部括號,首先與【】結合,因為【】優先順序比*高,說明P1是一個數組指標。在往右看是第二個括號),然後往左看遇到第一個*,說明陣列指標裡面的元素是一個指標,什麼型別的指標呢?跳出第二個括號,往右是引數列表,說明陣列中包含的是函式指標,這些函式double (*p) ( double k )型別,返回值型別是double */
使用typedef分解 double (* (* P1)[1] )( double (*p) ( double k ) );
第一步:typedef double ( * ppt )( double k );==> double (* (* P1)[10] )( ppt k );
第二部:typedef ppt (*p)[1];==> 此時如果定義一個變數 (p a;),那麼a的型別將和P1的型別一致
使用typedef分解 double ( * (* (*fp3)( double(*u)(double k) ) ) [1] )( double k );
/* 如果把 (*fp3)( double(*u)(double k) ) 替換成P1,那麼將和上面舉的例子相同 */
第一步:typedef p (*fp3)( ppt point );//返回型別是一個數組指標,所以p是一個數組指標型別
第二步:typedef ppt (*p)[1];//定義一個數組指標,陣列指標所指向的陣列具有“函式指標,指向形參為double,返回為double”的特徵
第三步:typedef double ( * ppt )( double k );//定義一個函式指標,指向形參為double,返回為double的函式
貼上測試型別程式碼:
#include <stdio.h>
typedef double ( * ppt )( double k );
typedef ppt (*p)[1];//p的型別為 ppt (*)[1];
typedef p (*fp)( ppt point );//定義一個函式指標,引數也是一個函式指標typedef double ( *(* (*fp3)( double(*u)(double k) ) )[1] )( double k );
int main ()
{
fp3 jj;
fp qq;
jj = qq;return 0;
}//沒有報錯,說明使用typedef分解正確
最後貼上使用例項,以幫助大家更詳細的瞭解:
#include <stdio.h>
typedef double ( * ppt )( double k );
typedef ppt (*p)[1];//p的型別為 ppt (*)[1];
typedef p (*fp)( ppt point );//定義一個函式指標,引數也是一個函式指標//跟前面一樣,先找到變數名fp3(這裡fp3其實是新型別名),往右看是圓括號,調轉方向往左是*,說明fp3是一個指標;跳出圓括號,
//往右看是ppt型別的引數,說明fp3是一個函式指標,接著往左是*號,說明該函式的返回值是一個指標;跳出第二層圓括號,往右是[]運算子,
//說明函式的返回值是一個數組指標,接著往左是*號,說明陣列中包含的是指標;跳出第三層圓括號,往右是引數列表,說明陣列中包含的
//是函式指標,這些函式有一個double的形參,返回值型別是double。簡言之,fp3是一個指向函式的指標,所指向的函式具有ppt型別引數返回double型別的值,
//且返回一個含有1個數組指標,並且該陣列指標所指向的陣列具有ppt型別並且步長一樣的陣列。
typedef double ( *(* (*fp3)( double(*u)(double k) ) )[1] )( double k );//typedef double *(*P2[10])();//指標陣列,數組裡面的元素是函式指標,指向沒有引數返回值為double型別的函式
//typedef double (* (* P1)[10])();//陣列指標,第一個*說明陣列中包含的是指標,往右是引數列表,說明陣列中包含的是函式指標,這些函式沒有引數,返回值型別是double
/* 如果max函式的型別定義為 P2,則會報錯,因為函式不允許反回陣列
P1 max( int *k )
{
P1 pt;
return 0;
}*/double test( double result )
{
return result;
}/* 引數point為指向ppt(返回值為double,引數為double型別的引數)型別的指標 */
p func( ppt point )
{
ppt b[1] = { point } ;//建立一個ppt型別的陣列,陣列元素為ppt型別
p point_b;//建立一個數組指標,用於指向ppt型別的陣列,注意步長要一樣
point_b = &b;
return point_b;
}int main ()
{
// ppt本身就是函式指標,ppt*為指向函式指標的指標
// ppt* point;
// point = &test;//報錯fp a;//定義一個fp型別的函式指標
ppt point_test;//定義一個ppt型別的函式指標a = &func;//&操作符只是顯示地說明了編譯器隱式執行的任務,a = func也可以
point_test = **a( &test );//*a( &test ),取得陣列b的地址。**a( &test ),取得陣列b裡面的內容,即test的地址printf( "%f\n", point_test(3.14));
getchar();}
參考連結:
https://www.cnblogs.com/Lunais/p/5969181.html
https://blog.csdn.net/skywalker_leo/article/details/48622193