by xvirk on 10/23/16, 10:27 PM with 68 comments
by stephencanon on 10/23/16, 11:05 PM
The correct rule is "follow the C grammar". An easier to remember and also correct rule is "start at the identifier being declared; work outwards from that point, reading right until you hit a closing parenthesis, then left until you hit the corresponding open parenthesis, then resume reading right..." (this is sometimes called the "right-left rule"[2]).
The "spiral rule" dances around the truth without actually being precise enough to be useful.
[1] https://news.ycombinator.com/item?id=5079787 [2] http://ieng9.ucsd.edu/~cs30x/rt_lt.rule.html
by colanderman on 10/23/16, 11:40 PM
const char *foo[][50]
the following expressions have the following types: foo -> const char *[][50]
foo[0] -> const char * [50]
foo[0][0] -> const char *
*foo[0][0] -> const char
Another example: int (*const bar)[restrict]
bar -> int (*const)[restrict]
*bar -> int [restrict]
(*bar)[0] -> int
One more: int (*(*f)(int))(void)
f -> int (*(*)(int))(void)
(*f) -> int (* (int))(void)
(*f)(0) -> int (* )(void)
*(*f)(0) -> int (void)
(*(*f)(0))() -> int
(In this case, the last expression is more readily written as f(0)(), since pointers to functions and functions are called using the same syntax.)by kazinator on 10/24/16, 1:39 AM
To follow the declaration you make use of the fact that postfix operators in have a higher precedence than unary, and that of course unary operators are right-associative, whereas postfix are left-associative (necessarily so, since both have to "bind" with their operand).
So given
int ***p[3][4][5];
we follow the higher precedence, in right to left associativity: [3], [4], [5]. Then we run out of that, and follow the lower-precedence * * * in right-to-left order.If there are parentheses present, they split this process. We go through the postfixes, and then the unaries within the parens. Then we do the same outside those parens (perhaps inside the next level of parens):
int ****(***p[3][4][5])[6][7];
1 2 3 4
765
8 9
1111
3210
Start at p, follow postfixes, then unaries within parens. Then the postfixes outside the parens and remaining unaries.The result is in fact a spiral just from going root postfix unary out postfix unary out. We just don't have to focus on the spiral aspect of it.
by robertelder on 10/23/16, 10:59 PM
by rfw on 10/23/16, 11:02 PM
int* arr[][10];
Spiral rule would state "arr is an array of pointers to arrays of 10 ints", where actually it would be "arr is an array of array of 10 pointers to int".Instead, when you write declarations, do it from right-to-left, e.g.:
char const* argv[];
"argv is an array of pointers to constant characters"It doesn't help with reading, unfortunately.
by gtrubetskoy on 10/23/16, 11:55 PM
str [10]*byte
which reads exactly as it is declared: "str is an array of length 10 of pointers to byte" (byte is Go equivalent of C char (mostly)).by fazkan on 10/24/16, 1:45 PM
(PS. Golang has the right idea, since its developed by the guys who contributed to C)...
by nine_k on 10/23/16, 11:15 PM
by ajarmst on 10/24/16, 1:31 AM
by jacquesm on 10/24/16, 12:15 PM
by generic_user on 10/24/16, 1:13 AM
Cdecl (and c++decl) is a program for encoding and decoding C (or C++) type declarations.
by sugarfactory on 10/24/16, 1:04 PM
by Chinjut on 10/24/16, 3:39 AM
by lisper on 10/23/16, 11:52 PM
foo(*baz(bing,boff(*bratz)(biff)))(buff);
by hilop on 10/24/16, 3:26 PM
It's been 20years(!) Why is this incorrect advise still up at c-faq?
by mrcactu5 on 10/24/16, 2:40 AM
(())()(()())(())
these count different arrangement of parentheses for function application. this guy is describing something like contour integration for computer programsby faehnrich on 10/24/16, 1:31 PM
by Buge on 10/24/16, 1:06 AM
by mtrycz on 10/24/16, 8:33 AM
Yeah, I know, I'm not good enough, I didn't study enough, I'm not enlightened enough. But why make things so overly comples in the first place?
by marcv81 on 10/24/16, 11:37 AM
by xyzzy4 on 10/24/16, 12:04 AM