Complex C declaration

后端 未结 8 1432
清歌不尽
清歌不尽 2020-11-30 18:47

I was just going through some code on the Internet and found this:

float * (*(*foo())[SIZE][SIZE])()

How do I read this declaration? Is the

相关标签:
8条回答
  • 2020-11-30 19:07

    I haven't done this in a while!

    Start with foo and go right.

    float * (*(*foo())[SIZE][SIZE])()

    foo is a function with no arguments...

    Can't go right since there's a closing parenthesis. Go left:

    float * (*(* foo())[SIZE][SIZE])()

    foo is a function with no arguments returning a pointer

    Can't go left further, so let's cross the parentheses and go right again

    float * (*(* foo())[SIZE][SIZE])() float * (*(* foo())[SIZE][SIZE])() float * (*(* foo())[SIZE][SIZE])()

    foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE ...

    Closing parenthesis reached, left again to reach a pointer symbol:

    float * (*(* foo())[SIZE][SIZE])()

    foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to ...

    Left parenthesis again, so we cross it and go right again:

    float *( *(* foo())[SIZE][SIZE])() float *( *(* foo())[SIZE][SIZE])()

    foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments...

    And left to the end

    float * ( *(* foo())[SIZE][SIZE])()

    foo is a function with no arguments returning a pointer to an array of SIZE arrays of SIZE pointers to a function with no arguments returning a pointer to float


    And whoever wrote that, please teach him to use typedef:

    // Function that returns a pointer to float
    typedef float* PFloatFunc ();
    
    // Array of pointers to PFloatFunc functions
    typedef PFloatFunc* PFloatFuncArray2D[SIZE][SIZE];
    
    // Function that returns a pointer to a PFloatFuncArray2D
    PFloatFuncArray2D* foo();
    
    0 讨论(0)
  • 2020-11-30 19:11

    from http://cdecl.org/

    declare foo as function returning pointer to array SIZE of array SIZE of pointer to function returning pointer to float

    0 讨论(0)
  • 2020-11-30 19:17

    This document gaves me the best clue about how to easily ready any C declaration :

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

    There are three simple steps to follow:

    • Starting with the unknown element, move in a spiral/clockwise direction; when ecountering the following elements replace them with the corresponding english statements:

      • [X] or [] => Array X size of ... or Array undefined size of ...

      • (type1, type2) => function passing type1 and type2 returning ...

      • * => pointer(s) to ...

    • Keep doing this in a spiral/clockwise direction until all tokens have been covered.

    • Always resolve anything in parenthesis first!

    Example :

                 +-------+
                 | +-+   |
                 | ^ |   |
            char *str[10];
             ^   ^   |   |
             |   +---+   |
             +-----------+
    
    Question we ask ourselves: What is str?
    
    ``str is an...
    
    - We move in a spiral clockwise direction starting with `str' and the first character we see is a `[' so, that means we have an array, so...
      ``str is an array 10 of...
    
    - Continue in a spiral clockwise direction, and the next thing we encounter is the `*' so, that means we have pointers, so...
      ``str is an array 10 of pointers to...
    
    - Continue in a spiral direction and we see the end of the line (the `;'), so keep going and we get to the type `char', so...
    ``str is an array 10 of pointers to char''
    
    We have now ``visited'' every token; therefore we are done!
    
    0 讨论(0)
  • 2020-11-30 19:20

    According to cdecl.org

    declare foo as function returning pointer to array SIZE of array SIZE of pointer to function returning pointer to float

    Use the spiral rule given by Luchian Grigore if you want to decode it by hand.

    0 讨论(0)
  • 2020-11-30 19:20

    The best thing to do here is convert to a series of typedefs.

    typedef float * fnReturningPointerToFloat();
    typedef fnReturningPointerToFloat* fnArray[SIZE][SIZE];
    fnArray* foo();
    
    0 讨论(0)
  • 2020-11-30 19:22

    Standard rule: find the leftmost identifier and work your way out, remembering that [] and () bind before *:

                foo                      -- foo
                foo()                    -- is a function
               *foo()                    -- returning a pointer
              (*foo())[SIZE]             -- to a SIZE-element array
              (*foo())[SIZE][SIZE]       -- of SIZE-element arrays
             *(*foo())[SIZE][SIZE]       -- of pointers
            (*(*foo())[SIZE][SIZE])()    -- to functions
          * (*(*foo())[SIZE][SIZE])()    -- returning pointers
    float * (*(*foo())[SIZE][SIZE])();   -- to float
    

    So imagine you have a bunch of functions returning pointers to float:

    float *quux();
    float *bar();
    float *bletch();
    float *blurga();
    

    Let's say you want to store them in a 2x2 table:

    float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
    

    tab is a SIZE x SIZE array of pointers to functions returning pointers to float.

    Now let's decide we want a function to return a pointer to that table:

    float *(*(*foo())[SIZE][SIZE])()
    {
      static float *(*tab[SIZE][SIZE])() = {quux, bar, bletch, blurga};
      return &tab;
    }
    

    Note that you could have several functions that build tables of different functions, or organize the same functions differently:

    float *(*(*qwerbl())[SIZE][SIZE])()
    {
      static float *(*tab[SIZE][SIZE])() = {blurga, bletch, bar, quux};
      return tab;
    }
    

    which is the only reason I can think of to do something like this. You shouldn't see types like this in the wild very often (although they do crop up occasionally, and I've been guilty of writing something similarly heinous).

    0 讨论(0)
提交回复
热议问题