首先,來看乙個簡單的例子:
int a1; /*a1是乙個int*/
int a2; /*a2是乙個陣列,它的每乙個元素是乙個int*/
int * a3; /*a3是乙個陣列,它的每乙個元素是乙個int *(即,它的每乙個元素是乙個指向int的指標)*/
int (* a4); /*a4是乙個指標,它指向乙個int陣列*/
可能上面的3、4兩行比較容易混淆,加不加括號其實區別很大。
比如說,如果我這麼寫:
int * a3[10];
int (* a4)[10];
對於上面的那一行來說,a3是乙個陣列,它的每乙個元素是乙個int指標,它一共包含10個這樣的元素
在32位機上,乙個指標型變數(不論它指向什麼),他的大小都是4個位元組,因此對於上面那一行,a3被分配的儲存空間是:40個位元組
對於下面的那一行來說,a4是乙個指標,它指向乙個int陣列,而那個陣列具有10個元素
根據上面的解釋,任何型別的指標所佔的儲存空間是4個位元組,那麼這裡也不例外,因此對於下面那一行,a4被分配的儲存空間是:4個位元組
接下來還有乙個容易產生混淆的情況:
int i = 10;
const int * p1 = &i; /*p1是乙個指向整型的指標,不能通過p1來修改i的值*/
int const * p2 = &i; /*p2是乙個指向整型的指標,不能通過p2來修改i的值*/
int * const p3 = &i; /*p3是乙個指向整型的指標,p3不能再指向除i以外的其他整型變數*/
上面的p1和p2其實是等價的,兩種寫法都正確。
關於const的辨析,可以總結為:
如果const出現在 * 的左邊,則無法通過這個指標修改所指向的變數
如果const出現在 * 的右邊,則這個指標從此以後無法再指向別的變數
我認為這個詞不應該被解釋為常量,而應該解釋為不可修改或二進位制保護
請看下面這個例子:
const int i = 10;
int * p = &i;
*p = 100;
printf ("%d\n", *p); /*列印100*/
printf ("%d\n", i); /*列印100*/
上面這個例子的測試在vs2010及gcc 4.8.3上均通過了測試(注意,我們這裡使用的是c編譯器,而不是c++編譯器)
編譯器會在int * p = &i;這一行發出乙個警告:(但不是錯誤)
initialization discards 『const』 qualifier from pointer target type(初始化丟失了const限定符)
然後我們成功地通過p修改了i的值
所以const常量並非真正的常量,它唯一的作用是防止你通過特定的識別符號來修改記憶體中的某些值,在這裡的情況是你不能通過i = 100來修改i的值
但你完全可以用上面所展現的這種曲徑通幽的方法來達到修改的目的
int * (*foo[10])(char *, int);
那麼foo究竟是個什麼東西呢?
我們一步步地來分析:
所以foo的型別應該很明了了,我就不具體書寫出來了(因為很長),但你現在肯定已經知道它究竟是個什麼東西了。
那麼我們該怎麼分析乙個c語言的宣告呢?
我認為,應該從宣告的兩端尋找需要的資訊,然後對這一過程,遞迴地進行下去
從左端找:它是什麼型別?int ?float ?某種你自己定義的struct ?,它是不是某種*(指標)?
從右端找:它是不是乙個(陣列)?,它是不是乙個()(函式)?如果是函式,它接收哪些形參?
這裡沒有涉及諸如const,static,extern等限定符的情況,但即使出現了限定符,你也應該已經能夠正確地解析它們了
最後,談一談為什麼要這麼做
為什麼有些人要寫一些像這樣複雜的宣告,然後我們還要去學習怎麼解釋這樣複雜的宣告呢?
這算不算是一種奇技淫巧呢?
坦白的講,我認為——算
這樣的宣告,就像玩雜技一樣,上下(左右)翻飛,令人眼花繚亂
但是我還想說,c(以及c++)
就是一門奇技淫巧的語言
在那個年代,記憶體受限(往往以kb計算),cpu效能受限,編譯器的功能受限(以至於這些所謂的高階程式語言,在當時其實是很不方便的)
人們不得不想出很多辦法,來實現一些語言中沒有的特性,比如說人們就用到了函式指標這種東西,它後來幾乎成為了奇技淫巧的代名詞
奇技淫巧,畢竟也是一種技,也是一種巧,它們在特定的歷史時期,解決了特定的問題
它們至今還活躍在你所使用的編譯器的**中,你所使用的作業系統的**中
我們在面對奇技淫巧的時候,要端正心態,不要一味地去追逐奇技淫巧,從而達到炫技的目的
也不能一味地排斥一些能夠解決特定問題的特定技術
比如上面關於較複雜的c語言宣告的解析,就能夠幫助你讀懂許多c語言的原始碼
然後你才有能力思考,**的原作者為什麼要這樣設計?
碼,為人所用
解析C語言宣告
在學習c語言的過程中,會先遇到陣列指標,指標陣列此類的概念。這些概念實在是晦澀難懂,在進一步學習之後,你會發現更加恐怖的還有各種各樣的宣告,比如 char const next 那麼這些宣告到底是什麼意思呢?序號說明 a宣告從他的名字開始讀取,然後按照優先順序順序依次讀取 b優先順序從高到低依次是 ...
深入解析C語言宣告
如果說c語言宣告很簡單的人不是牛人就是還沒入門。本文來講解c語言的宣告的一些基本內容,很多內容參考 c專家程式設計 首先由乙個最簡單的問題引入,你知道 int p 5 和 int p 5 的區別在 嗎?把後面的答案遮到,想想。也許你知道反正乙個是含有五個指向整型的指標元素的指標陣列,另乙個是指向乙個...
深入解析C語言宣告
如果說c語言宣告很簡單的人不是牛人就是還沒入門。本文來講解c語言的宣告的一些基本內容,很多內容參考 c專家程式設計 首先由乙個最簡單的問題引入,你知道 int p 5 和 int p 5 的區別在 嗎?把後面的答案遮到,想想。也許你知道反正乙個是含有五個指向整型的指標元素的指標陣列,另乙個是指向乙個...