为何不精通C? 03 深入剖析声明
??? 對于復雜的C函數(shù)聲明,或者被typedef別名后的聲明,很多人往往一頭霧水。本文主要解析下C語言中聲明過程所遵循的原則。
聲明
??? 引用《C專家編程》的第三章內容,說明下聲明的優(yōu)先級規(guī)則:
- ?括號包圍的地方
- 后綴操作符:
- 括號()表示是一個函數(shù)
- 方括號[]表示是一個數(shù)組
- 前綴操作符:星號*表示類型是 指向....的指針
不過,我覺得這個規(guī)則的不夠通俗,看了《C++Annotation》中關于const的那一章節(jié),也詳細解釋了下這個規(guī)則,高效,庖丁解牛般分析:
// 例子char* const *(*next)();
通俗的乒乓解釋,就是從變量名開始,碰到)或結束往左讀,碰到(往右讀。
遇到*()[]解釋之
其中 解釋是函數(shù)的話,需解釋其形參表及返回值
?????? 解釋為數(shù)組的話,需解釋數(shù)組元素是什么
?????? 解釋為指針時,需解釋其指向什么類型
舉例:
1 next 名叫next, 開始往右讀,碰到了),折向往左 2 (*next) 遇到* ,解釋是一個指針 繼續(xù)往左讀碰到(, 折向往右 3 (*next)() 遇到(),解釋指向一個函數(shù),該函數(shù)沒有形參 到末尾,折向往左4 *(*next)() 遇到*,解釋函數(shù)返回一個指針,關于函數(shù)的形參表和返回值解釋完畢 , 繼續(xù)往左 5 char* const *(*next)() 先碰到const,再是*, 最后是char, 解釋函數(shù)的返回值(指針)指向一個char型指針常量,即指針不可賦新值,所指的值可以改變。到開頭,結束。
以上的例子是函數(shù)的聲明舉例。
對其他的聲明也是一樣的,比如之前文章中? int *ap[], 我們也是這樣解釋的:
- 從 ap 開始往右讀,碰到了[], 說明是一個數(shù)組
- 然后到末尾,折向向左,碰到*,說明數(shù)組的元素是指針,
- 最后碰到int,說明該元素的指針類型為 int*
常規(guī)的 const int * p; 也可以這么來:
- 從 p 開始,結尾折向,往左走。
- 先碰到*, 說明是一個指針
- 再碰到 int,const, const修飾的是int, 則說明該指針指向一個const int東西
同理,對于 int* const p: 我們在往左看時,先看到了const,再*, 說明const修飾的是*。
來個復雜的挑戰(zhàn)下吧:
char* const* (* const (*(*ip)() ) [] ) [] (*ip) ip是一個指針 (*ip)() ip是一個函數(shù)指針,該函數(shù)無形參 *(*ip)() 函數(shù)返回一個指針 (...)[] 該指針指向一個數(shù)組 *const (...)[] 數(shù)組元素為 常量指針 (*const (...)[]) [] 該常量指針指向一個數(shù)組 char* const* {...}該數(shù)組內元素為指向char型常量指針的指針 合起來就是:ip是一個函數(shù)指針(無形參), 返回一個指向數(shù)組的指針,該數(shù)組內元素為常量指針,其指向一個元素為char型常量指針的數(shù)組。不過,一般不會有這種聲明來惡心我們的。。我們基本上知道怎么打乒乓就行了。
typedef
剖析完了聲明,一般來說還要說下 typedef ,這可是C的一大神器呀。
首先,我們要明確的是,typedef是為類型創(chuàng)建別名,而不是創(chuàng)造新的類型。
講typedef時,又必須和 #define做下區(qū)分, define僅是簡單的宏擴展
主要來說,有以下的區(qū)別:
- 首先,可以對其他類型說明符采用宏類型名進行擴展,但對typedef所定義則不行
- 其次,連續(xù)變量聲明中,typedef能夠保證所有定義類型一致,而#define不能保證
和typedef做好朋友
void (*signal(int sig, void(*func)(int))) (int);
我們來分析下這個是什么東西:
??? signal(..) : signal 是一個函數(shù),有復雜的形參表
??? *signal(...) : 返回值是一個指針
??? void {*}(int) : 該指針指向一個函數(shù),該函數(shù)的形參為int, 這個函數(shù)的返回值是void
我們看看signal的形參表: 兩個參數(shù),一個參數(shù)是 int; 另外個參數(shù) void(*func)(int) 是一個函數(shù)指針,該函數(shù)有一個int形參,返回void;
對比下,我們可以分析出, signal的返回值和 func的定義一樣, 都是 void(*)(int), 但若是采用這種寫法的話,不好看懂,這時候,我們的好朋友typedef就出現(xiàn)了:
typedef void(*ptr_to_func)(int); ptr_to_func signal(int, ptr_to_func){.....}另外,typedef也經(jīng)常和struct配合使用。
typedef struct my_struct{....} NewName;這樣,NewName 就等同于 struct my_struct , 少打了struct這幾個字符
擴展說下 聲明和定義的區(qū)別:
C語言中,對象有且僅有一個定義,而聲明卻可以有多個extern 聲明。
定義:只能出現(xiàn)在一個地方,確定同時分配內存,它是特殊的聲明
聲明:只是描述其他地方創(chuàng)建對象的屬性。有extern前綴,作用于變量
具體的一些擴展區(qū)別,見后續(xù)博文,關于指針和數(shù)組的闡釋
END
要點: 怎么打乒乓?typedef是個別名好朋友
轉載于:https://www.cnblogs.com/IntellX/archive/2013/05/17/3083701.html
總結
以上是生活随笔為你收集整理的为何不精通C? 03 深入剖析声明的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小程序事件参数传递
- 下一篇: C# 对轻量级(IoC Containe