首页 > 解决方案 > ANSI C - 直接声明符语法 - 为什么 C 语法允许语法上合法但语义上非法的声明,如 int func()()?

问题描述

ANSI C 语法规定:

declarator:
    pointer_opt direct-declarator

direct-declarator:
    identifier
    ( declarator )
    direct-declarator [ constant-expression_opt ]
    direct-declarator ( parameter-type-list )
    direct-declarator ( identifier-list_opt )

根据这个语法,可以推导出

func()()

作为声明者,并且

int func()()

作为声明,这在语义上是非法的。为什么 C 语法允许这种语法上合法但语义上非法的声明?

标签: csyntaxgrammardeclarationc89

解决方案


这类问题通常无法确定地回答,因为您正在询问有关1989 年C 委员会的集体思想和审议的信息。他们从未像负责 Python 的人那样完全公开地进行语言开发工作,而 30 年前他们这样做的更少。如果你亲自对他们进行调查,他们可能不会记得。

我们可以查看C Rationale 文档(我链接到与 C1999 对应的版本,但据我所知,它自 1989 年以来并没有太大变化)寻找线索,但快速浏览一下,我看不到与您的问题相关的任何内容。

这让我根据编程语言设计的一般原则进行猜测。有一个与您的问题相关一般原则:特别是对于较旧的语言,设计人员试图使形式语法尽可能地与上下文无关。这使得编写高效的解析器变得更加容易。诸如“你不能有一个返回函数的函数”之类的规则需要上下文,因此它们被排除在语法之外。将它们作为应用于解析树的事后约束来处理很简单,这就是设计人员所做的。

C 语法有一大堆地方似乎已经使用了这个原则,而不仅仅是你要问的那个。例如,存在用于标记化的“最大咀嚼”规则是因为它意味着标记器不需要知道完整的解析器上下文,即使它会导致不方便的结果,例如a-----b被解释为a -- -- - b而不是a -- - -- b,即使解析器将拒绝前者,接受后者。

这种编程语言的设计原则常常令初学者感到惊讶,因为它与人类理解自然语言的方式大不相同。我们会不遗余力地从最荒谬的句子中“修复”某种上下文适当的含义,我们实际上在对话中依赖于此。考虑越差越好的元原则可能会有所帮助(过于简单化,因为您可以快速完成前 90% 的工作并将其放在那里,然后对剩余的 90% 进行迭代)。


推荐阅读