pointer的宣告一般一定會知道的就是 *符號
如同加減乘除這些operator都有優先權
宣告的時候也有它的優先權
一般解釋優先權時,會以括號「()」作為輔助說明
而 pointer的 *符號的優先權的括號又是怎麼界定?
最簡單的例子
int *ptr;
以最明確(explicit)的宣告方式來說
應該是這個樣子
int (*ptr)
這是告訴 compiler,ptr是一個 pointer,而這個pointer所指向的type是 int
那麼接下來有幾個 case,case數字越大,使用的頻率會越少,提出來僅供參考
1. array的 pointer
依照使用經驗,大部分的人直接認為array的 pointer不就一般 type的 pointer?
很可惜是有差別的,差別在所指向的 type
array在assign給其他變數的時候和pointer互通
請注意只有在此時才有等效性,基本上是不相同的兩樣事物
什麼type的array就等效於什麼樣的type的pointer
例如int等效於 int的pointer、char的array等效於char的pointer
那 int array的array,也就是俗稱的二維陣列呢,那自然就是 int array的pointer啦
array的pointer,所指向是 array
換句話說使用時,dereference回去後看到是一個array
假設需要一個 size為 10的 array pointer,宣告方式就必須如下
int (*arrptr)[10];
這樣宣告以後,array就不能以 = 直接 assign給這個 pointer,因為type不同了
假設有一個 array是 int arr[10];
assign時必須很明確的告訴 compiler,arrptr = &arr
且也不能 array一樣直接使用 []作為 element的存取
[] opertaor相當於 offset後 dereference
因為看到的 type不同,offset的計算也不一樣了
因此必須 dereference後才能像 array一般的使用,如 (*arrptr)[5]
事實上 arr和 &arr的值是一模一樣的
但是在C語言的 type上是不同的
一個是 int *,而另一個是 int (*) [10]
螞蟻書上寫得好像都可以通用是很容易誤導的
若直接以 arrptr[5] 存取是在告訴compiler
移動5個單位的位移量,單位的大小是 10個int,
換句話說就是 5 * 10 * 4 (現今一般電腦的 int記憶體占用量 ) 個bytes
並取得的東西是 int[10]這個大小為10的int array,如果我們要的是int
想把它存進int的變數,compiler運作起來就是個不符需求的語意
2. 回傳值是 pointer的 function,一個最耳熟能詳的宣告方式
int *func(); 或 int (*func());
若不以括號明確的劃分清楚,任何的pointer都會被歸到回傳值去
若將 identifer連同參數 ()一起括起來,即表示 function的回傳值是 pointer
以這個 case,func是一個回傳 pointer的 function,
並且是 int的 pointer
3. function的 pointer
int (*fptr)()
從以上的例子以此類推
它告訴 compiler,fptr是一個pointer,而pointer所指向的type是
「回傳值為 int且不須任何參數的 function」
這裡稍微說明一下,括號類的符號一律擺在最後邊
最左邊的 type與最右邊的括號一組
並且括號由右向左解析,等等可以看到其他例子
4. function pointer的 array
int (*fptrarr[SIZE])()
它告訴 compiler,fptrarr是一個 size為 SIZE的 pointer array
而 pointer所指向的 type是
「回傳值為 int且不須任何參數的 function」
不要括錯了,如果寫成這樣
int (*fptrarr)[SIZE]()
那就變成是 fptrarr是一個 pointer,
pointer指向的 type是一個 array,什麼的 array
回傳值為 int 的 function的 array(不是 function pointer的 array喔)
這種 type 在 compiler的語意上是不合法的
因為 function是不保證有固定size的,沒辦法變成 array
5. 回傳值是一個 array pointer的 function
int (*func())[SIZE];
從前面的例子解讀,可以知道 func的是一個回傳值為 pointer的 function
而 pointer所指向的 type為 size為 SIZE的 int array(int (*) [SIZE])
這個例子和 case 2都有一個問題,就是沒有辦法直接回傳 local array
因為 local array會隨著 function跳出而被「消滅」
因此大部分搭配使用 malloc
為了避免麻煩我們先對 int [SIZE] 做一個 typedef
typedef int INTARR[SIZE];
INTARR (*func())
typedef 很難記嗎?不會
用法和一般宣告一模一樣,只差在有一個typedef而已
如果怕宣告太複雜不會寫,就多多利用 typedef來作思考轉換吧
6. 回傳值是一個 function pointer (或者可以視為 function)的 function
這邊要強調的是回傳 function和回傳 function pointer在實質上還是不同的
就如同 array和 pointer一樣,但有等效作用
其實是有回傳值為 function的 function,但是為 C語言語意錯誤編譯不給過的
因為回傳值是以 pass by value的方式傳送,function並沒有固定 size
compiler根本無從得知應配置多少記憶體量儲存
並且複製至另一記憶體區並無任何意義,也沒辦法100%保證能夠運作
可以試試看 int func()();
而本 case的宣告方式為
int (*func())();
func的回傳值是一個 pointer,而這個 pointer所指向的是
「一個回傳值為 int且不須任何參數的 function」
同樣為了避免麻煩我們先對 function做一個 typedef
typedef int RIntFuncType();
RIntFuncType *func();
2012/04/09 撰 2014/04/30 第一次修訂 2014/05/28 第二次修訂 |
相關文章 無 |
留言列表