通过K& R的C书,第2版

时间:2015-08-18 19:21:40

标签: c declaration semantics

我刚刚阅读了第二版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星评价?

1 个答案:

答案 0 :(得分:0)

这是因为声明反映了使用。

在声明的语法中,声明符被分成指针部分,后跟直接声明符,其中应用了数组形成[]和函数形成()结构,因此形成了数组或函数类型的优先级高于形成指针类型。

并且,反映这一点,在表达式的语法中,后缀运算符[]()的优先级高于前缀一元运算符*

这意味着,当我们看到int *f()时,我们知道这是一个返回指向int的指针的函数,因为*f()给出的值为int;同样我们知道char (*g)()是指向返回char的函数的指针,因为(*g)()必须提供类型为char的值。

这就是允许错误进入附录A的原因;没有人会读它,因为应用声明 - 反映 - 使用规则会得到正确的结果,并且更容易应用。