开发者

Complex declarations

开发者 https://www.devze.com 2022-12-14 00:51 出处:网络
How do I interpret complex declarations like: int * (* (*fp1) (int) ) [10]; ---> declaration 1 int *( *( *[5])())(); --------> declaration 2

How do I interpret complex declarations like:

int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2

Is there any rule that should be followed to understand the above开发者_如何学Go declarations?


Here is a great article about how to read complex declarations in C: http://www.codeproject.com/KB/cpp/complex_declarations.aspx

It helped me a lot!

Especially - You should read "The right rule" section. Here quote:

int * (* (*fp1) (int) ) [10]; This can be interpreted as follows:

  1. Start from the variable name -------------------------- fp1
  2. Nothing to right but ) so go left to find * -------------- is a pointer
  3. Jump out of parentheses and encounter (int) --------- to a function that takes an int as argument
  4. Go left, find * ---------------------------------------- and returns a pointer
  5. Jump put of parentheses, go right and hit [10] -------- to an array of 10
  6. Go left find * ----------------------------------------- pointers to
  7. Go left again, find int -------------------------------- ints.


You can use cdecl*:

cdecl> explain int *( *( *a[5])())();
 declare a as array 5 of pointer to function
 returning pointer to function returning pointer to int
cdecl> explain int * (* (*fp1) (int) ) [10];
 declare fp1 as pointer to function (int) returning
 pointer to array 10 of pointer to int

*Linked is a website that uses this command line tool in the backend.


I've learned the following method long ago:

Start from the type identifier (or the inner parenthesis) and move following a spiral taking the element at right first

In case of

 int * (* (*fp1) (int) ) [10];

You can say:

  • fp1 is a (nothing on the right so move left)
  • pointer to (move out of the inner parenthesis
  • a function taking int as agument (the 1st on the right)
  • and returns a pointer to (exit from parenthesis)
  • an array of 10 elements of type
  • pointer to (nothing left on the right)
  • int

Resulting in:

fp1 is a pointer to a function taking an int and returning a pointer to an array of 10 pointers to int

Drawing the actual spiral (in you your mind, at least) helps a lot.


For solving these complicated declarations, the rule you need to keep in mind is that the precedence of function-call operator () and array subscript operator [] is higher than dereference operator *. Obviously, parenthesis ( ) can be used to override these precedences.

Now, work out your declaration from the middle, which means from the identifier name.

int * (* (*fp1) (int) ) [10]; --->declaration 1

Based on the precedences rule mentioned above, you can easily understand it by breaking down the declaration as

fp1 * (int) * [10] * int

and read it directly from left-to-right in English as "fp1 is a pointer to a function accepting an int & returning a pointer to an array [10] of pointers to int". Note that the declaration is broken this way only to help understand it manually. The compiler need NOT parse it this way.

Similarly,

int *( *( *[5])())(); -------->declaration 2

is broken as

[5] * () * () * int

So, it declares "an array [5] of type pointers to function () which returns a pointer to a function () which in turn returns a pointer to int".


Though it's has been answered already, but you may also read this article :

http://unixwiz.net/techtips/reading-cdecl.html


Start with the leftmost identifier and work your way out, remembering that absent any explicit grouping [] and () bind before *, e.g:

    *a[]                 -- is an array of pointer
  (*a)[]                 -- is a pointer to an array
    *f()                 -- is a function returning pointer
  (*f)()                 -- is a pointer to a function

Thus, we read int *(*(*fp1)(int))[10] as:

         fp1                     -- fp1
        *fp1                     -- is a pointer
       (*fp1)(int)               -- to a function
                                      taking an int parameter
      *(*fp1)(int)               -- returning a pointer
     (*(*fp1)(int))[10]          -- to a 10-element array
    *(*(*fp1)(int))[10]          -- of pointer 
int *(*(*fp1)(int))[10]          -- to int

The declaration int *(*(*[5])())() presents a bit of a challenge since there's no identifier; you typically see this in function declarations where a parameter is of that type:

void foo(int *(*(*[5])())(), double);

It's the same principle as the unnamed int parameter in the declaration of fp1. The array gives us the clue, you can also look for the leftmost inner grouping of parentheses.

                         -- unnamed
         [5]             -- is a 5-element array ([] binds before *)
        *[5]             -- of pointers
       (*[5])()          -- to functions
      *(*[5])()          -- returning pointers
     (*(*[5])())()       -- to functions
    *(*(*[5])())()       -- returning pointers
int *(*(*[5])())()       -- to int


The clockwise/spiral:

* http://c-faq.com/decl/spiral.anderson.html


No, you don't need to read it loud with complex steps like "clockwise/spiral rule" and "the right rule". Why should you? You only need to know how to use it! Don't make the simple one complex.

C declarations in fact work in a simple rule: declare as how would be used.

Consider the code you gives out:

int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2

For the first declaration, this means that *(*(*fp1)(int))[int] is an int. And that's it.

For example, you know that *(*(*fp1)(5))[0] is an int, and *(*(*fp1)(2))[9] is an int too.

And The second declaration is incomplete. Even gcc won't know what you want to convey.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号