【问题标题】:how to understand C99 standard syntax如何理解 C99 标准语法
【发布时间】:2012-04-25 13:05:22
【问题描述】:

我不太明白 C99 中的语法是什么意思。这里所说的 C99 是指 ISO/IEC 9899:1999。好吧,我认为语法部分自 ANSI C、C89 以来并没有太大变化。

this question为例:

6.5.5 Multiplicative operators
  Syntax
    multiplicative-expression:
      cast-expression
      multiplicative-expression * cast-expression
      multiplicative-expression / cast-expression
      multiplicative-expression % cast-expression

  Constraints

Each of the operands shall have arithmetic type. The operands of the % operator
shall have integer type.

  Semantics

The usual arithmetic conversions are performed on the operands.
The result of the binary * operator is the product of the operands.
The result of the / operator is the quotient 

我想知道为什么在乘法运算符的语法中我们有一个“cast-expression”?这个语法可以暗示什么语法?在that question@Avi 说在

a*b*c

“c 必须被解析为强制转换表达式”,我不太明白。

再举一个c99 6.6.1的例子,常量表达式的语法

Syntax
   constant-expression:
       conditional-expression

为什么这个条件表达式会出现在这里? 有人可以告诉我如何解释这些语法吗?谢谢大家。

【问题讨论】:

    标签: c c99 iso


    【解决方案1】:

    我想知道为什么在乘法运算符的语法中我们有一个“cast-expression”?

    这是上下文无关文法中使用的典型设备,用于指定具有相同优先级的运算符的分组并首先指定优先级(好吧,这并不精确;文法可以表达的不仅仅是分配优先级给运算符,但如果我们只想在 CFG 中表达简单的基于优先级的表达式求值,我们会这样做)。 cast-expressionmultiplicative-expression 无关;它只是“任何不包含乘法运算或低优先级运算的表达式”。

    那么,这将如何工作:

    1. 同优先级运算符的分组:

      1*2*3*4
      

      在这种情况下,有以下分组可能性(仅限顶级):

      • 1*(2*3*4)
      • (1*2)*(3*4)
      • (1*2*3)*4

      通过查看语法,我们知道* 左侧的任何内容都必须是cast-expression,也就是说,不得包含(未加括号的)*。因此,只有第三种方案是可行的

    2. 优先级。想象一下表情

      a*b+c
      

      它可以被解析为任一

      • (a*b)+c
      • a*(b+c)

      但是,我们知道右侧的 cast-expression 不能包含(未加括号的)+(或者,如果我们检查它,我们可以从语法中解决它)。这使得第一个选项成为唯一可能的选择。

      另一种表达方式

      a+b*c
      

      可以依次解析为

      • (a+b)*c
      • a+(b*c)

      但是,* 左侧的 multiplicative-expression 也不能包含(未加括号的)+(留作练习供读者使用)。因此,只有第二种方案是可行的。

    关于条件表达式的问题:语法规则不允许将任何等效或低于赋值运算符的内容解析为constant-expressions。因此,a=ba,ba+=b 不可能是常量表达式,而 a+ba[b]a(b) 可能可以。请注意,它不允许例如。 (a=b);您必须查看指定什么是常量表达式的实际子句,这比语法更限制了常量表达式的范围。

    【讨论】:

    • 我可以看到,如果我们只是把cast-expression当作不是multiplicative-expression的表达式,那么我们就可以知道乘法表达式的结合性。但是,cast-expression 本身在 c99 中确实有语法 6.5.4.1,我们不需要确保示例表达式中的 'c' 是 cast-expression?你能解释一下conditional-expression 部分吗?
    • 这意味着我们也可以简单地将cast-expression 更改为conditional-expression 吗?
    • 强制转换运算符恰好是比乘法运算符优先级高的一系列运算符。标准的整个运算符优先级章节以相同的方式构建。是的,它非常不清楚和令人困惑,就像关于标准中表达式的整章一样。
    • @AllanRuin:“但是,cast-expression 本身在 c99 6.5.4.1 中确实有语法,我们不需要确保示例表达式中的 'c' 是 cast-expression?”我们当然需要。然后我们查看标准,看到cast-expression -> unary-expressionunary-expression -> postfix-expressionpostfix-expression -> primary-expressionprimary-expression -> identifier-> 表示“可以重写”)。 c 是一个标识符,因此可以解析为cast-expression
    【解决方案2】:

    我想知道为什么在乘法运算符的语法中我们有一个“cast-expression”?

    让我们从一个更简单的问题开始,以及相应更简单的语法。我们将定义一个语法来表示一个简单的算术表达式(1 + 23 * (4 - 2)42 等)。因为我们希望一个普通的数字常量是一个合法的表达式,我们必须定义我们的语法,使得有一条从根非终结符表达式到一个简单的数字的路径:

    表达式术语 | 术语附加操作表达式 术语因素 | 因子 mul-op 项 因素号码 | (表达式)

    numberadd-opmul-op 等非终结符应该很明显。

    42是一个数字,是factor的产生,term的产生,term的产生表达式。因此42 根据我们的语法是合法的算术表达式; termfactor 是这条路径的中间产物。

    类似的事情发生在 C 语法中。 cast-expressionexpression 和某个终结符(例如标识符或数字常量)之间的中间产生式。我们的简单语法定义了 2 个优先级; C 语法定义了 16 个不同的优先级,其中包含更多的运算符,因此沿着这条路径有更多的中间产品。我们希望 cast-expression 具有比 multiplicative-expression 更高级别的优先级,这样我们就可以处理像

    这样的情况
    x = a * (int) b;
    

    正确。

    【讨论】:

      猜你喜欢
      • 2011-05-13
      • 2011-07-23
      • 1970-01-01
      • 2017-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-02
      • 2012-11-09
      相关资源
      最近更新 更多