我刚刚阅读了第二版K& R“The C Programming language”的语言参考(附录A),以获得新工作。
请注意,我已经制定了如何通过SO的所有指导来阅读C声明(非常感谢;))。解释一直是对C.中表达式和运算符的优先级的引用 我可以从参考手册a.k.a.附录A,§A7中推断出相同的优先级表,没问题。
但是,§A7处理表达式运算符的优先级,如本节开头所述 - 方括号postfix-expression [ expression ]
在此被视为下标运算符,星号*
被查看因为间接运算符和括号( argument-expression-list)
或()
与函数调用有关,请参见§A7.3。
那么为什么这么多人会引用这个优先级表,当主题是C声明时,甚至会在SO上得到几个赞成?它声称定义的唯一优先级是某些表达式运算符。
如何解析声明是在§A8中编写的,尤其是§A8.6进入了更为复杂的声明的基础。
但是在整个附录A中,没有关于优先顺序的说法,括号,方括号,星号,类型名称等都要进行解析。
它在第216页说,括号可能会改变复杂声明符的绑定,但现在如何(虽然我有预感,请参阅下面的示例)。
让我举一个“伪代码”的例子,其中我 am 使用§A8.8(T代表类型说明符,D代表声明符)是亏本的:
阅读C声明:
Original declaration:
char (*(*f())[])()
/* Have to use A8.6.3, because of how the decl. looks: */
Now let T=char , D=(*(*f())[])()
D=D1(), where D1=(*(*f())[])
The type of f, according to A8.6.3 is then
:L1 /* label 1 */
f is "type-modifiers of f in D1" function returning char /* note, in the book it says 'type-modifiers of f in T D1, but this wouldn't make any sense! */
Now look at T D1 = char (*(*f())[])
:ALT_A
The type of f in D1 = (*(*f())[]) is the same as that of f in
D2=*(*f())[]
/* At least, this is how parentheses are supposed to be understood, according to the beginning of A8.6,
where it says:
In a declaration T D where D has the form
( D1 )
then the type of the identifier in the declaration D1 is the same as that of D. */
/* note about that quote: the identifier in D has no type, did the authors mean to imply 'incomplete' types?
So, using incomplete types:*/
Looking at D2 = T1 D3[] ----> have to use A8.6.2, where T1 = * , D3 = (*f()),
so the type of f in T1 D3 is
f is "type-modifiers of f in D3" array of pointers ()
look at f in D3 = (*f()), or equivalently, f in D4 = *f(). Have to use A8.6.3. --->
f is a function returning a pointer to ()
going up a level: f is "type-modifiers of f in D3" array of pointers ()
translates to: f is a function returning a pointer to an array of pointers ()
going up another level: f is "type-modifiers of f in D1" function returning char
translates to: f is a function returning a pointer to an array of pointers to functions returning a char
这是结果,cdecl也显示了。 请注意,我没有使用任何优先级表,只使用参考手册和直接与声明相关的部分。
那么这么多人如何以及为什么会提到运营商优先权呢? 在我看来,当人们询问C语句时,每次引用运算符优先级都是错误的答案,给出了一个“解析算法”,神奇地证明它能给出正确的结果。
其次,为什么K& R似乎与如此多的事情如此不精确(请参阅我的/ * * / - 伪代码中的备注)?我本来期望更精确,我的意思是他们显然知道所有的细节,并且必须能够精确地思考。
抱歉搞乱了格式化,顺便说一下..我今天大部分时间都在试着写下我如何手动解析这个问题,同时了解K& R可能对这个和那个公式有什么意义......
声明的列表,其中声明与运算符优先级相关联:
http://users.ece.utexas.edu/~ryerraballi/CPrimer/CDeclPrimer.html (“所有人都必须理解任何复杂的C声明,就是要知道这些声明基于C运算符优先级图表,与用于计算C语言中的表达式的表示相同:”)
http://binglongx.com/2009/01/25/how-to-read-a-cc-declaration/
How are (complex) declarations parsed in terms of precedence and associativity? (“事实上,C的设计者足够明智地使声明使用与表达式相同的”优先规则“。这是”声明遵循使用“规则。例如,在表达式”中,请参阅Brian的第一个答案。“
Operator precedence in C Definitions
专家C编程:Deep C Secrets,p。 74,28在Google图书上评论5星评价?
答案 0 :(得分:0)
这是因为声明反映了使用。
在声明的语法中,声明符被分成指针部分,后跟直接声明符,其中应用了数组形成[]
和函数形成()
结构,因此形成了数组或函数类型的优先级高于形成指针类型。
并且,反映这一点,在表达式的语法中,后缀运算符[]
和()
的优先级高于前缀一元运算符*
。
这意味着,当我们看到int *f()
时,我们知道这是一个返回指向int
的指针的函数,因为*f()
给出的值为int
;同样我们知道char (*g)()
是指向返回char
的函数的指针,因为(*g)()
必须提供类型为char
的值。
这就是允许错误进入附录A的原因;没有人会读它,因为应用声明 - 反映 - 使用规则会得到正确的结果,并且更容易应用。