從一個指針的聲明淺談和函數、數組有關的指針
最近閑來無聊隨手翻《C++ primer plus》時遇到了一個看起來十分複雜令人頭疼的聲明:
const double *(*(*pd)[3])(const double *,int) = &pa;
關於如何在理論上分析這樣複雜的指針聲明,希望這篇文章對其他被類似問題困擾的像我這樣的小白有幫助。
指針對於像我這樣的C/C++初學者來說確實是一個不小的難題,指針又能延伸出許多容易搞混的東西:二維數組和指針數組,函數指針和返回值為指針變數的函數。
一切關於指針的聲明都可以根據運算符的優先順序和結合性來分析。
——某位化名渣哥的大佬
在和函數、數組有關的指針中可能會涉及到的運算符的優先順序和結合性如下:
[]數組下標,2級,左結合
()形參列表,2級,左結合
*解除引用,3級,右結合
值得注意的是運算符()的另一種用法:和數學中的括弧一樣,調整運算符的運算順序
接下來我們看一下二維數組的指針數組都是什麼?
有一回(孔丙己)對我說道,「你寫過代碼么?」我略略點一點頭。他說,「寫過代碼,……我便考你一考。二維數組做函數參數,形參怎樣寫的?」我想,討飯一樣的人,也配考我么?便回過臉去,不再理會。孔丙己等了許久,很懇切的說道,「不能寫罷?……我教給你,記著!這些寫法應該記著。將來做程序員的時候,讀代碼要用。」我暗想我和程序員的等級還很遠呢;又好笑,又不耐煩,懶懶的答他道,「誰要你教,不是數組名加上行和列的下標么?」孔丙己顯出極高興的樣子,將兩個指頭的長指甲敲著鍵盤,點頭說,「對呀對呀!……二維數組做函數形參有三種基本寫法,你知道么?」
——魯樹人《孔丙己》
剛學二維數組時被二維數組的形參和指針數組搞得一臉懵逼,自然只用第一種寫法
void function(int a[3][4]);//一個四行三列的二維數組做參數
然而實際上,一維的下標可以省略,像這樣
void function(int a[][4]);//一個二維數組做參數
話說回來,一個二維數組除了可以看成一個矩陣之外,還可以看成一個元素是一維數組的一維數組,所以二維數組還可以寫成這種指向數組的指針的形式,而這種形式最容易和指針數組弄混
void function(int (*a)[4]);//一個二維數組做參數void function(int *a[4]);//一個指針數組做參數
那麼函數指針和返回值為指針變數的函數的形式又是什麼?
int (*function)(int a);//函數指針(指向函數的指針,本質上來講是指針)int * function(int a);//返回值為指針變數的函數(本質上來講是函數)
大致回顧了一下和這類問題有關的基礎知識
接下來要做的就是一層一層一步一步(當然,如果你能一眼看出來當我沒說)地分析這種聲明
第一步
(*pd);//pd是一個指針
第二步
(*pd)[3];//pd指向一個包含三個元素的數組
第三步
(*(*pd)[3])(const double *, int);//這個數組的元素為函數指針(函數形參為一個指向double常變數的指針和一個int變數)
第四步
const double *(*(*pd)[3])(const double *, int);//函數指針指向的函數的返回一個指向double的指針(函數的返回值的基類型為double *)
第五步
const double *(*(*pd)[3])(const double*, int) = &pa;//將一個地址(符合條件)賦值給指針pd
推薦閱讀:
※當"老經驗"遇到"新場景"——學習方式的陷阱
※滿分文書大全|如何寫一份招生官都拒絕不了的CS文書
※給計算機初學者的書籍推薦
※刷頂會必備 ?』?』 ? 2018年人工智慧頂會月曆