Complex C declaration

后端 未结 8 1433
清歌不尽
清歌不尽 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:22

    Generally, you could try cdecl.org but you'd need to substitute for SIZE

    Say you swap SIZE for 12, you'd get:

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

    I'm not sure that really helps you!

    Two observations here:

    1. I'm guessing that this code didn't have a comment beside it explaining what the purpose of it was (i.e. not the technical explanation of what it is but what it is achieving from a functional / business perspective) If a programmer needs to use something as complex as this, they should be good enough to explain to future maintainers what purpose it serves.
    2. Certainly in C++ there are more obvious and probably safer ways of achieving the same thing.
    0 讨论(0)
  • 2020-11-30 19:25

    Although most of the answers above are good enough, there is a lack of complete set of rules for decoding complex C declarations. I have provided a complete set below to decode any complex C declaration. This set of rules is actually based on the precedence of operators. Rules such as right hand spiral rules can be thought of as a shortcut for these set of rules.

    Before anything else we need to know a few things to decode the declaration.

    'Basic Type' of a declaration

    A C declaration always has only one basic declaration type. This is at the left most position of a declaration. For example -

    • int a - basic type is 'int'
    • float *p - basic type is 'float'
    • char (*p)[3] - basic type is 'char'

    Precedence and associativity

    Next we need to know the precedence order of (), [], and * - dereference operator

    1. (), [] - Associativity is left to right
    2. * - Associativity is right to left

    Phrase corresponding to each of the operator above

    Next we need to know the decoded phrase corresponding to each operator. Examples ahead will make this point clear.

    • () - function returning
    • [SIZE] - array of SIZE
    • * - pointer to

    Now follow the rules below to decode the declaration

    1. Always write the variable name first followed by an 'is'.

      For example -

    • int a - a is ...
    • float *p - p is ...
    • char (*p)[3] - p is ...
    1. Always end with basic type

      For example -

    • int a - a is ... int
    • float *p - p is ... float
    • char (*p)[3] - p is ... char
    1. Now fill the part in between using the following sub-steps

      • Starting from the name, follow the operator precedence and associativity to choose next highest priority operator and append the phrase corresponding to it to the middle part of the decoded string.

      • Repeat the sub step above for the remaining declaration until the decoding process is complete

    NOTE 1: For simplicity, I have ignored the arguments of the function however it can be included just after the phrase corresponding to ().

    NOTE 2: Parenthesis(()) change the priority order of operators, just like in any arithmetic expression.

    NOTE 3: You can use parenthesis in the decoded declaration to increase readability( I have done it in some examples below). Think of each set of () as a single unit.

    NOTE 4: A n dimensional array is actually an array of array of ... (n-1 times) array. For ex - int A[2][3] - A is array of 2 (array of 3 int) i.e A is an array of 2 elements in which each element is an array containing 3 integers

    Examples

    • int a - a is int
    • float *p - p is pointer to float
    • char (*p)[3] - p is pointer to array of 3 char

    Some complex declaration examples

    1. int **p[10] - p is array of 10 pointer to pointer to int
    2. int (*p)[10] - p is pointer to array of 10 int
    3. int *p(char *a) - p is function returning pointer to int
    4. int (*p(char*a))[10] - p is function returning (pointer to (array of 10 int))
    5. int *(*p)() - p is pointer to (function returning (pointer to int))
    6. int (*p()[20])[10] - p is function returning (array of 20 (pointer to (array of 10 int)))

    This set of rules can be used with const as well - const qualifier modifies the term to the left of it (if present) otherwise it modifies the term to the right of it.

    1. const int *p[10] - p is array of 10 pointer to int const
    2. int const *p[10] - p is array of 10 pointer to const int (this is same as 7th example)
    3. int *const p[10] - p is array of 10 const pointer to int

    Now a really complex example which will not find its use anywhere in practice but nevertheless can be used to demonstrate the decoding process

    1. char *(*(**foo[][8])())[] - foo is array of (array of 8 (pointer to (pointer to (function returning (pointer to (array of (pointer to char)))))))

    Now at last decoding for the declaration given in the question

    float * (*(*foo())[SIZE][SIZE])() - foo is function returning (pointer to (array of SIZE (array of SIZE (pointer to (function returning pointer to float)))))

    The following is the link for the article from which I read this decoding process

    Example 10 has been taken from this article

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

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