close
"Right-Left" Rule

The "right-left" rule is a completely regular rule for deciphering C
declarations. It can also be useful in creating them.

First, symbols. Read

* as "pointer to" - always on the left side
[] as "array of" - always on the right side
() as "function returning" - always on the right side

as you encounter them in the declaration.

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 function returning". Or if you found a
"[]" there, you would say "identifier is 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. Here are some
examples:
 
注意此符號到關鍵字的左邊. 假若沒有上述所說的符號(也就是像 "int" 之類的符號), 正如所言. 否則, 使用上述的表格將其轉譯成文字形式, 續往左直到超出符號邊界或者左邊括弧 "(".
 
現在重複步驟二及三直到你已正規化你的宣告. 以下是幾個範例:


int *p[];

1) Find identifier.

int *p[];
^
"p is"

2) Move right until out of symbols or left parenthesis hit.
int *p[];
^^
"p is array of"

3) Can't move right anymore (out of symbols), so move left and find:
int *p[];
^
"p is array of pointer to"

4) Keep going left and find:
int *p[];
^^^
"p is array of pointer to int".
(or "p is an array where each element is of type pointer to int")

 

Another example:

int *(*func())();

1) Find the identifier.

int *(*func())();
^^^^
"func is"

2) Move right.

int *(*func())();
^^
"func is function returning"

3) Can't move right anymore because of the right parenthesis, so move left.
int *(*func())();
^
"func is function returning pointer to"

4) Can't move left anymore because of the left parenthesis, so keep going
right.

int *(*func())();
^^
"func is function returning pointer to function returning"

5) Can't move right anymore because we're out of symbols, so go left.
int *(*func())();
^
"func is function returning pointer to function returning pointer to"

6) And finally, keep going left, because there's nothing left on the right.
int *(*func())();
^^^
"func is function returning pointer to function returning pointer to int".


As you can see, this rule can be quite useful. You can also use it to
sanity check yourself while you are creating declarations, and to give
you a hint about where to put the next symbol and whether parentheses
are required.

Some declarations look much more complicated than they are due to array
sizes and argument lists in prototype form. If you see "[3]", that's
read as "array (size 3) of...". If you see "(char *,int)" that's read
as "function expecting (char *,int) and returning...". Here's a fun
one:

int (*(*fun_one)(char *,double))[9][20];

I won't go through each of the steps to decipher this one.

Ok. It's:

"fun_one is pointer to function expecting (char *,double) and
returning pointer to array (size 9) of array (size 20) of int."

As you can see, it's not as complicated if you get rid of the array sizes
and argument lists:

int (*(*fun_one)())[][];

You can decipher it that way, and then put in the array sizes and argument
lists later.

Some final words:

It is quite possible to make illegal declarations using this rule,
so some knowledge of what's legal in C is necessary. For instance,
if the above had been:

int *((*fun_one)())[][];

it would have been "fun_one is pointer to function returning array of array of
^^^^^^^^^^^^^^^^^^^^^^^^
pointer to int". Since a function cannot return an array, but only a
pointer to an array, that declaration is illegal.


Illegal combinations include:

[]() - cannot have an array of functions
()() - cannot have a function that returns a function
()[] - cannot have a function that returns an array

In all the above cases, you would need a set of parens to bind a *
symbol on the left between these () and [] right-side symbols in order
for the declaration to be legal.

Here are some legal and illegal examples:

int i; an int
int *p; an int pointer (ptr to an int)
int a[]; an array of ints
int f(); a function returning an int
int **pp; a pointer to an int pointer (ptr to a ptr to an int)
int (*pa)[]; a pointer to an array of ints
int (*pf)(); a pointer to a function returning an int
int *ap[]; an array of int pointers (array of ptrs to ints)
int aa[][]; an array of arrays of ints
int af[](); an array of functions returning an int (ILLEGAL)
int *fp(); a function returning an int pointer
int fa()[]; a function returning an array of ints (ILLEGAL)
int ff()(); a function returning a function returning an int
(ILLEGAL)
int ***ppp; a pointer to a pointer to an int pointer
int (**ppa)[]; a pointer to a pointer to an array of ints
int (**ppf)(); a pointer to a pointer to a function returning an int
int *(*pap)[]; a pointer to an array of int pointers
int (*paa)[][]; a pointer to an array of arrays of ints
int (*paf)[](); a pointer to a an array of functions returning an int
(ILLEGAL)
int *(*pfp)(); a pointer to a function returning an int pointer
int (*pfa)()[]; a pointer to a function returning an array of ints
(ILLEGAL)
int (*pff)()(); a pointer to a function returning a function
returning an int (ILLEGAL)
int **app[]; an array of pointers to int pointers
int (*apa[])[]; an array of pointers to arrays of ints
int (*apf[])(); an array of pointers to functions returning an int
int *aap[][]; an array of arrays of int pointers
int aaa[][][]; an array of arrays of arrays of ints
int aaf[][](); an array of arrays of functions returning an int
(ILLEGAL)
int *afp[](); an array of functions returning int pointers (ILLEGAL)
int afa[]()[]; an array of functions returning an array of ints
(ILLEGAL)
int aff[]()(); an array of functions returning functions
returning an int (ILLEGAL)
int **fpp(); a function returning a pointer to an int pointer
int (*fpa())[]; a function returning a pointer to an array of ints
int (*fpf())(); a function returning a pointer to a function
returning an int
int *fap()[]; a function returning an array of int pointers (ILLEGAL)
int faa()[][]; a function returning an array of arrays of ints
(ILLEGAL)
int faf()[](); a function returning an array of functions
returning an int (ILLEGAL)
int *ffp()(); a function returning a function
returning an int pointer (ILLEGAL)

 

Operator

Description

Associativity

()
[]
.
->
++  --
Parentheses (function call) (see Note 1)
Brackets (array subscript)
Member selection via object name
Member selection via pointer
Postfix increment/decrement (see Note 2)

left-to-right

++  --
+  -
!  ~
(type)
*
&
sizeof 
 
Prefix increment/decrement
Unary plus/minus
Logical negation/bitwise complement
Cast (change type)
Dereference
Address
Determine size in bytes
right-to-left
*  /  % Multiplication/division/modulus left-to-right
+  - Addition/subtraction left-to-right
<<  >> Bitwise shift left, Bitwise shift right left-to-right
<  <=
>  >=
Relational less than/less than or equal to
Relational greater than/greater than or equal to
left-to-right
==  != Relational is equal to/is not equal to left-to-right
& Bitwise AND left-to-right
^ Bitwise exclusive OR left-to-right
| Bitwise inclusive OR left-to-right
&& Logical AND left-to-right
|| Logical OR left-to-right
?: Ternary conditional right-to-left
=
+=  -=
*=  /=
%=  &=
^=  |=
<<=  >>=
Assignment
Addition/subtraction assignment
Multiplication/division assignment
Modulus/bitwise AND assignment
Bitwise exclusive/inclusive OR assignment
Bitwise shift left/right assignment
right-to-left

,

Comma (separate expressions) left-to-right
Note 1:
Parentheses are also used to group sub-expressions to force a different precedence; such parenthetical expressions can be nested and are evaluated from inner to outer.
Note 2:
Postfix increment/decrement have high precedence, but the actual increment or decrement of the operand is delayed (to be accomplished sometime before the statement completes execution). So in the statement  y = x * z++; the current value of z is used to evaluate the expression (i.e., z++evaluates to z) and z only incremented after all else is done. See postinc.c for another example.

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 Bluelove1968 的頭像
    Bluelove1968

    藍色情懷

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