這文章是有位外國討論區網友所提供的資料,這篇文章發表於comp.lang.c Newsgroups,作者覺得相當的不錯,
值得提供給網友們做學習,作者只是將內容翻譯整理並且加入作者個人的經驗。
對C語言來說,以右到左的規則來描述宣告時所代表的意義,首先在宣告中你會到的符號有(紅色作者加的):
符號(symbol) |
閱讀 |
* |
pointer
to |
指向 |
[
] |
an
array of |
的陣列 |
(
) |
a
function returning |
一個函數,傳回 |
接下來有三個步驟可以幫助你對於C的宣告的描述有所認識
STEP 1
------
Find the identifier(識別字,變數名稱). This is your starting point. Then say to yourself,
"identifier is". You've started your declaration.
STEP 2
------
Look at the symbols on the right of the identifier. If, say, you find "()"
there, then you know that this is the declaration for a function. So you
would then have "identifier is a function returning". Or if you found a
"[]" there, you would say "identifier is an array of". Continue right until
you run out of symbols *OR* hit a *right* parenthesis ")". (If you hit a
left parenthesis, that's the beginning of a () symbol, even if there
is stuff in between the parentheses. More on that below.)
STEP 3
------
Look at the symbols to the left of the identifier. If it is not one of our
symbols above (say, something like "int"), just say it. Otherwise, translate
it into English using that table above. Keep going left until you run out of
symbols *OR* hit a *left* parenthesis "(".
Now repeat steps 2 and 3 until you've formed your declaration.
假設你看到"[3]",讀成"an array (size 3) of ..."
假設你看到"(char *,int)",讀成"a function expecting(char *,int) and return ..."
文字描述你可能不清楚在說什麼,現在舉個例子:
EX1:
int *x;
Step(1)identifier(識別字;變數名稱):x
int *x;
=>解釋成《x is》
Step(2)往右看沒有任何符號,所以往左看,看到*
int *x;
=>解釋成《x is pointer to》
Step(3)右邊已沒有任何符號,所以繼續往左看,看到int
int *x;
=>解釋成《x is pointer to int》
=>作者改成《x is a pointer to integer》
=>作者解釋成【x是一個指標,指向int】
EX2:
int x[3];
Step(1)identifier(識別字;變數名稱):x
int x[3];
=>解釋成《x is》
Step(2)往右看,看到[3]
int x[3];
=>解釋成《x is an array (size 3) of 》
Step(3)接著往左看,看到int
int x[3];
=>解釋成《x is an array (size 3) of int》
=>作者解釋成【x是一個大小為3的int陣列】
EX3:
int *x[3];
Step(1)identifier(識別字;變數名稱):x
int *x[3];
=>解釋成《x is》
Step(2)往右看,看到[3]
int *x[3];
=>解釋成《x is an array (size 3) of 》
Step(3)接著左看,看到*
int *x[3];
=>解釋成《x is an array (size 3) of pointer to 》
Step(4)因為右邊的符號已經閱讀完畢,無任何符號可以閱讀,所以繼續往左看,看到int
int *x[3];
=>解釋成《x is an array (size 3) of pointer to int 》
=>作者翻譯成:【x是一個陣列,大小為3,而陣列元素為int指標】
EX4:
int (*x)[3];
Step(1)identifier(識別字;變數名稱):x
int (*x)[3];
=>解釋成《x is》
Step(2)往右看,看到右括號,所以往左看,看到*
int (*x)[3];
=>解釋成《x is pointer to》
Step(3)接著往左看,遇到左括號,所以往右看,看到[3]
int (*x)[3];
=>解釋成《x is pointer to an array of》
Step(4)接著往左看,看到int
int (*x)[3];
=>解釋成《x is pointer to an array of int》
=>作者解釋成:【x是一個指標 ,指向大小為3的int陣列】
EX5:
int *(*x())();
Step(1)identifier(識別字;變數名稱):x
int *(*x())();
=>解釋成《x is》
Step(2)往右看,看到()
int *(*x())();
=>解釋成《x is a function returning 》
Step(3)再往右看,因為遇到右括號,所以往左看,看到*
int *(*x())();
=>解釋成《x is a function returning pointer to 》
Step(4)接著往左看,因為遇到左括號,所以往右看,看到()
int *(*x())();
=>解釋成《x is a function returning pointer to a function returning 》
Step(5)接著往右看已沒有符號,所以往左看看,看到*
int *(*x())();
=>解釋成《x is a function returning pointer to a function returning pointer to》
Step(6)因為右邊符號已閱讀完畢,已無任何符號,所以繼續往左看,看到int
int *(*x())();
=>解釋成《x is a function returning pointer to a function returning pointer to int》
=>作者改成《x is a function which returns a pointer to another function which takes no parameters
and returns a pointer to an integer》
=>作者解釋成【x是一個沒有參數的函數,會傳回一個函式指標,指向沒有參數的函數,
此函數回傳一個指標,指向整數 】
先在此花一分鐘重新看一次,問自己一下,以下這兩個,那一個是指標,那一個是陣列呢?
(1)int *x[3];
(2)int (*x)[3];
接著問自己一下,以下這兩個,那些是指標,那些是函數呢?
(1)int (*x)(int,int));
(2)int (*x(int,int));
(3)int x(int,int);
Ans:
(1)x is a pointer to function which takes int and int as parameters and return type is integer.
(2)x is a function which takes int and int as parameters and returns a pointer to integer.
(3)x is a function which takes int and int as parameters and returns integer.
其實只要注意operator precedence(運算子優先順序),就能辨別那一個運算子是修飾identifier
*(deference),[](subscript),()(function all)的優先順序是: [] > () > *
EX: int *x[3]; //*的precedence小於[],所以[]會先修飾identifier:x,所以x是一個陣列
EX: int (*x)[3]; //因為括號()的關於,*會先修飾identifier:x,所以這是一個指標
EX: int (*x()); //因為()的precedence大於*,所以()會先修飾identifier:x,x是一個函數
不過並不是隨便寫都是函數,看這一個,合不合法:
int *((*x)())[3][3];
x is a pointer to function takes no parameter and returns a two-dimension array of pointer to int
會發生什麼問題呢?函數竟然傳回陣列哦!!!當然是不行,編譯器會出現error : function returns array
雖然宣告不合法,但還是可以解釋的。
最後在測試自己解釋這兩個:
(1)int (*(*X)(int ,double))[3][3];
(2)int (*X(int ,double))[3][3];
自己可以測試看看,不懂的地方歡迎尋問!
雖複雜的宣告可能並不會真得出現於實際的程式中,但希望以上的介紹能有助於學習。
當然如果覺得複雜的話,可以使用typedef來分解它,這部份先不討論。
可以參考:
C Language Reference : Interpreting More Complex Declarators
C Language Reference : Typedef Declarations
How to interpret complex C-C++ declarations - The Code Project - C++ - MFC
Written By James On 2007/01/15