【问题标题】:Why is "static;" valid C syntax?为什么是“静态的”;有效的 C 语法?
【发布时间】:2021-12-08 17:01:49
【问题描述】:

我正在查看C11 Standard PDF (第463页),我对声明的词汇语法感到困惑。看起来像这样的代码在 C11 中似乎在语法上是有效的:

static;
static const int;
long int const typedef long;

即使这样的声明似乎没有任何用处。


具体来说,让我困惑的是这里的这一部分:

declaration: 
  declaration-specifiers init-declarator-list<opt> ;

declaration-specifiers:
  storage-class-specifier declaration-specifiers<opt>
  type-specifier declaration-specifiers<opt>
  type-qualifier declaration-specifiers<opt>
  function-specifier declaration-specifiers<opt>
  alignment-specifier declaration-specifiers<opt>

似乎声明中的 init-declarator-list 已明确设为可选。没有它的声明还有用吗?

【问题讨论】:

  • 这似乎与first constraint 相矛盾:除了 static_assert 声明之外的声明应至少声明一个声明符(函数的参数或结构或联合的成员除外)、标签或枚举的成员。
  • @Julius 声明符在函数原型的参数列表中是可选的。
  • 我看到有一个约束!但我仍然不明白为什么它在语法中是可选的。参数列表似乎没有引用声明非终结符?
  • 也许它在过去是(意外地)允许的,并且他们通过允许编译器继续接受它来保持兼容性(尽管有诊断)。 /// 或者他们可能喜欢用语法中的(可能是空的)列表来定义事物,并在需要的地方添加约束。

标签: c syntax grammar c11


【解决方案1】:

(这不是 C 标准;它是一个非官方草案。第 463 页是非规范性文本——它只是提供信息,而不是标准的约束性部分。此答案使用官方 C 2018 标准,该标准具有仅对 2011 年标准进行技术更正和澄清。)

仅就 C 标准中的形式语法而言,declaration 产生式,如 C 2018 6.7 1 所示,可能是 declaration-specifiers init-declarator -list选择;。其中,declaration-specifiers 可以产生 storage-class-specifier declaration-specifiersopt init-declarator-list 可能不存在,给出 storage-class-specifier declaration-specifiersopt;。那么后面的declaration-specifiers可能不存在,给storage-class-specifier;,最终可以产生static;

但是,C 标准的规则超越了语法。 C 2018 6.7 2 说:

除了 static_assert 声明之外的声明应至少声明一个声明符(函数的参数或结构或联合的成员除外)、标记或枚举成员。

声明 static ; 没有声明声明符、标记或枚举的任何成员,因此它违反了此约束。然后一个符合标准的 C 实现必须为它发出一个诊断消息,尽管它可能仍然接受它。

staticconstint;longintconsttypedeflong;也违反了这个约束。

此外,C 2018 6.7.2 2 说:

每个声明的声明说明符中至少应给出一个类型说明符,...

由于static ; 没有类型说明符,例如voidintlong double _Complex,它也违反了这个约束。

似乎声明中的 init-declarator-list 已明确设为可选。没有它的声明还有用吗?

是的,我们可以有效地声明结构、联合和枚举标签,如struct foo { int x; };。这声明了struct foo 类型并且没有init-declarator(在主级别;当然,里面嵌套了一个)。

我们还可以声明枚举常量,如struct foo { apple, banana };。这在任何级别都没有 init-declarator

存在没有 init-declarator 的有用声明这一事实意味着 init-declarator 必须在生产中保持为可选,或者必须拆分生产分成两个产生式,一个允许声明结构等没有 init-declarator,另一个产生带有强制 init-declarator 的声明。据推测,使语法表示复杂化的麻烦不值得减少语义约束的好处。

【讨论】:

    猜你喜欢
    • 2013-10-14
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 2011-05-06
    • 2010-10-25
    • 1970-01-01
    • 2017-11-01
    • 2014-09-27
    相关资源
    最近更新 更多