Try   HackMD

指標篇 - 筆記

複雜宣告

常會看到一些很複雜的宣告

要理解這些宣告可以簡單的用以下規則來判斷

規則 補充
1.從內往外讀 先找變數名稱
2.先往右看 是否為 Function? Array?
3.再往左看 是否為 pointer?
4.先處理括號內的 Type values
5.最後的 Type 是什麼 int? long?
念法用以下替換
Function Function returning
Array Array of X elements , which are
* Pointer to
Type Type values

直接看規則可能看不懂,看下面例子說明

舉例

int *var[5]; ^ ^ ^ ^ 4 3 1 2
  1. 先找變數名稱 : var is declared as
  2. 先往右看是一個大小為 5 的 Array : Array of 10 elements, which are
  3. 再往左看是 * : Pointer to
  4. 最後是 Type : int values

合併就是 : var is declared as Array of 10 elements, which are Pointer to int values

中文就是 : var 被宣告為一個 10 大小的陣列,陣列裡的元素為指向 int 的指標

int (*var)[5]; ^ ^ ^ ^ 4 2 1 3
  1. var is declared as
  2. 因為 var 被括號包住,所以先看括號裡面的 : Pointer to
  3. 往右看是一個大小為 5 的 Array : Array of 10 elements, which are
  4. 最後是 Type : int values

合併就是 : var is declared as Pointer to Array of 10 elements, which are int values

中文就是 : var 被宣告為一個指標,指向大小為 10 的陣列,陣列裡的元素的型態是 int

long *var( long, long ); ^ ^ ^ ^ 4 3 1 2
  1. var is declared as
  2. 往右看是一個 Function : Function returning
  3. 再往左看是 * : Pointer to
  4. 最後是 Type : long values

合併就是 : var is declared as Function returning Pointer to long values

中文就是 : var 被宣告為一個 Function,此 Function 會回傳指向 long 的指標

long (*var)( long, long ); ^ ^ ^ ^ 4 2 1 3
  1. var is declared as
  2. 因為 var 被括號包住,所以先看括號裡面的 : Pointer to
  3. 往右看是一個 Function : Function returning
  4. 最後是 Type : long values

合併就是 : var is declared as Pointer to Function returning long values

中文就是 : var 被宣告為一個指向 Function 的 pointer,此 Function 會回傳 long

struct both { int a; char b; } ( *var[5] )( struct both, struct both ); /* 可以先把前面一大堆看成一種 Type 就號,簡化如下 */ both ( *var[5] )( struct both, struct both ); ^ ^ ^ ^ 3 1 2 4
  1. var is declared as
  2. 往右看是一個大小為 5 的 Array : Array of 10 elements, which are
  3. 再往左看是 * : Pointer to
  4. 往右看是一個 Function : Function returning
  5. 最後是 Type : both values

合併就是 : var is declared as Array of 10 elements, which are Pointer to Function returning both values

中文就是 : var 被宣告為一個 10 大小的陣列,陣列裡的元素為指向 Function 的指標,此 Function 會回傳both 型態

呼叫 Function

上面是說明如何理解複雜的宣告,這裡說明如何呼叫 Function,首先有個宣告如下

void (*func_ptr)();

根據上述觀念就是 : func_ptr is declared as Pointer to Function returning void values

func_ptr 就是一個指向 Function 的指標而已

func_ptr array[3];

這樣表示有個大小為 3 的陣列,陣列裡存的元素都是指向 function 的指標

所以你可以把實作好的 function assign 給 array

void FuncA(){ printf("Hi! A"); } void FuncB(){ printf("Hi! B"); } void FuncC(){ printf("Hi! C"); } array[0]= &FuncA; array[1]= &FuncB; array[2]= &FuncC; /* 用以下方法呼叫 fcuntion */ (* (array[0]) )(); (* (array[1]) )(); (* (array[2]) )(); /* 等同於 */ FuncA(); FuncB(); FuncC();

所以這裡有一個重點是,當你要使用 Function Pointer 來呼叫 function 時

要使用 : (* (Function Pointer) )();

C Traps and Pitfalls 的案例

(*(void(*)())0)();

首先可以看出這是呼叫 fcuntion

(* (void(*)())0 )(); (void(*)())0 = ( void (*var)() )0 = (Function Pointer)0

再根據上述方法改寫成

var is declared as Pointer to Function returning void

結論如下

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

0 是一個位址,我們可以知道 0 這個位址存放一個 Function

此 Function 沒有參數也沒有回傳值,最後呼叫此 Function

void **(*d) (int &, char **(*)(char *, char **));

這題也可以簡單看成下面宣告

void **(*d) ( A, B);

那 d 再根據之前的方法來解釋為

d is declared as Pointer to Function returning Pointer to Pointer to void

參考資料

Microsoft : 如何了解複雜的宣告

tags C