TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

The Clockwise/Spiral Rule of C declarations

225 点作者 xvirk超过 8 年前

21 条评论

stephencanon超过 8 年前
This has been posted before[1], and the &quot;spiral rule&quot; is a load of hooey.<p>The correct rule is &quot;follow the C grammar&quot;. An easier to remember and also correct rule is &quot;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...&quot; (this is sometimes called the &quot;right-left rule&quot;[2]).<p>The &quot;spiral rule&quot; dances around the truth without actually being precise enough to be useful.<p>[1] <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=5079787" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=5079787</a> [2] <a href="http:&#x2F;&#x2F;ieng9.ucsd.edu&#x2F;~cs30x&#x2F;rt_lt.rule.html" rel="nofollow">http:&#x2F;&#x2F;ieng9.ucsd.edu&#x2F;~cs30x&#x2F;rt_lt.rule.html</a>
评论 #12777319 未加载
colanderman超过 8 年前
Way simpler: from inside out, read any subpart of the type as an expression. (Arrays have precedence over pointers, as usual.) The type that remains is that expression&#x27;s type. So e.g. given the type:<p><pre><code> const char *foo[][50] </code></pre> the following expressions have the following types:<p><pre><code> foo -&gt; const char *[][50] foo[0] -&gt; const char * [50] foo[0][0] -&gt; const char * *foo[0][0] -&gt; const char </code></pre> Another example:<p><pre><code> int (*const bar)[restrict] bar -&gt; int (*const)[restrict] *bar -&gt; int [restrict] (*bar)[0] -&gt; int </code></pre> One more:<p><pre><code> int (*(*f)(int))(void) f -&gt; int (*(*)(int))(void) (*f) -&gt; int (* (int))(void) (*f)(0) -&gt; int (* )(void) *(*f)(0) -&gt; int (void) (*(*f)(0))() -&gt; int </code></pre> (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.)
评论 #12776099 未加载
评论 #12781049 未加载
kazinator超过 8 年前
The real rule is that the type construction operators mirror the unary and postfix family of operators (declaration follows use). For instance unary * declares a pointer, mimicking the dereference operator, and postfix [] and () declare functions, mimicking array indexing and function call.<p>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 &quot;bind&quot; with their operand).<p>So given<p><pre><code> int ***p[3][4][5]; </code></pre> 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.<p>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):<p><pre><code> int ****(***p[3][4][5])[6][7]; 1 2 3 4 765 8 9 1111 3210 </code></pre> Start at p, follow postfixes, then unaries within parens. Then the postfixes outside the parens and remaining unaries.<p>The result is in fact a spiral just from going root postfix unary out postfix unary out. We just don&#x27;t have to focus on the spiral aspect of it.
robertelder超过 8 年前
I used to think of the spiral rule as being a good guide, but then a commenter on HN showed me otherwise:<p><a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=12053206" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=12053206</a>
评论 #12776069 未加载
rfw超过 8 年前
The rule is misleading in cases like:<p><pre><code> int* arr[][10]; </code></pre> Spiral rule would state &quot;arr is an array of pointers to arrays of 10 ints&quot;, where actually it would be &quot;arr is an array of array of 10 pointers to int&quot;.<p>Instead, when you write declarations, do it from right-to-left, e.g.:<p><pre><code> char const* argv[]; </code></pre> &quot;argv is an array of pointers to constant characters&quot;<p>It doesn&#x27;t help with reading, unfortunately.
评论 #12775902 未加载
评论 #12775913 未加载
gtrubetskoy超过 8 年前
Contrast the first example with Golang:<p><pre><code> str [10]*byte </code></pre> which reads exactly as it is declared: &quot;str is an array of length 10 of pointers to byte&quot; (byte is Go equivalent of C char (mostly)).
评论 #12776330 未加载
评论 #12776120 未加载
评论 #12776101 未加载
评论 #12777685 未加载
fazkan超过 8 年前
I read a paper somewhere from dennis ritchie, where he explained the development of C language, the pros and cons; and in there he mentioned that reading complex declarations is a problem in C, he said that if we had placed the * operator to the left of the type it was qualifying then it would have been easier to write and understand more complex declarations.<p>(PS. Golang has the right idea, since its developed by the guys who contributed to C)...
评论 #12779576 未加载
nine_k超过 8 年前
What makes me wonder is why C ended up with such a syntax. That is, its contemporary, Pascal, has a very straightforward, unambiguous syntax.
评论 #12776063 未加载
评论 #12775999 未加载
评论 #12776000 未加载
ajarmst超过 8 年前
Seems overly complex. The way I learned it, and now teach, is to read the type backwards (int const * is &#x27;pointer to const int&#x27;) for const correctness, but anything that requires more complex parsing by a human should just be typedef&#x27;d into submission.
jacquesm超过 8 年前
One problem with the web is that it will remember wrong information just as well as it will remember correct information.
generic_user超过 8 年前
While cdecl was probably written before some of you where born it still does precisely one thing and does it well.<p>Cdecl (and c++decl) is a program for encoding and decoding C (or C++) type declarations.<p><a href="http:&#x2F;&#x2F;linuxcommand.org&#x2F;man_pages&#x2F;cdecl1.html" rel="nofollow">http:&#x2F;&#x2F;linuxcommand.org&#x2F;man_pages&#x2F;cdecl1.html</a>
评论 #12776247 未加载
评论 #12776326 未加载
sugarfactory超过 8 年前
Once I tried to figure out how to parse complex C declarations just by reading the specification (<a href="http:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg14&#x2F;www&#x2F;docs&#x2F;n1570.pdf" rel="nofollow">http:&#x2F;&#x2F;www.open-std.org&#x2F;jtc1&#x2F;sc22&#x2F;wg14&#x2F;www&#x2F;docs&#x2F;n1570.pdf</a>), that is, without consulting guides for layman like this. But I gave up. I looked at what seemed a BNF-like description of the C grammar but I had no idea what it tells about the parsing rules. So I ended up using this guide: <a href="http:&#x2F;&#x2F;ieng9.ucsd.edu&#x2F;~cs30x&#x2F;rt_lt.rule.html" rel="nofollow">http:&#x2F;&#x2F;ieng9.ucsd.edu&#x2F;~cs30x&#x2F;rt_lt.rule.html</a> With this I managed to implement an imitation of cdecl.
Chinjut超过 8 年前
What is the value of bending ourselves to fit a confusingly designed old language, rather than bending the language to fit us? The very fact that articles like this have to be written indicates a failure of user interface design, which we needn&#x27;t forever perpetuate.
lisper超过 8 年前
Things break down utterly in the presence of typedefs. What is this?<p><pre><code> foo(*baz(bing,boff(*bratz)(biff)))(buff);</code></pre>
评论 #12776194 未加载
hilop超过 8 年前
The first red flag is that the rule says &quot;clockwise&quot; where there s clearly to way to distinguish clocwise from anticlockwise inside the code. Only the completely arbitrary choice of up&#x2F;down direction of the drawing affects clockwiseness.<p>It&#x27;s been 20years(!) Why is this incorrect advise still up at c-faq?
mrcactu5超过 8 年前
symbols with equal amount of open and close parentheses in order are counted by Catalan numbers<p><pre><code> (())()(()())(()) </code></pre> these count different arrangement of parentheses for function application. this guy is describing something like contour integration for computer programs
faehnrich超过 8 年前
Or, as the book Expert C Programming says, declarations in C are read boustrophedonically.
评论 #12778715 未加载
Buge超过 8 年前
I always heard of the right-left rule, which seems simpler and more accurate to me.<p><a href="http:&#x2F;&#x2F;ieng9.ucsd.edu&#x2F;~cs30x&#x2F;rt_lt.rule.html" rel="nofollow">http:&#x2F;&#x2F;ieng9.ucsd.edu&#x2F;~cs30x&#x2F;rt_lt.rule.html</a>
mtrycz超过 8 年前
I&#x27;d take the striking simplicity of a lisp anyday compared to this mess.<p>Yeah, I know, I&#x27;m not good enough, I didn&#x27;t study enough, I&#x27;m not enlightened enough. But why make things so overly comples in the first place?
marcv81超过 8 年前
This is the reason why golang declares the identifier before the type and the return value at the after the function parameters. This allows parsing any declaration from left to right.
xyzzy4超过 8 年前
Just don&#x27;t make complex declarations in C, it&#x27;s almost never useful and won&#x27;t help anyone out. It&#x27;ll confuse people and make your code write-only. Just put in a couple extra lines of code somewhere if you have to. It won&#x27;t be the end of the world.
评论 #12776156 未加载