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 第二次修訂  

  相關文章  

  無 

arrow
arrow
    文章標籤
    C pointer declare
    全站熱搜

    wylokgo101 發表在 痞客邦 留言(0) 人氣()