为什么 "static;" 有效的 C 语法?
Why is "static;" valid C syntax?
我在看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 似乎已明确设为可选。没有它声明还有用吗?
(这不是 C 标准;它是一个非官方草案。第 463 页是非规范性文本——它只是提供信息而不是标准的约束部分。这个答案使用官方 C 2018 标准,其中只有 2011 年标准的技术更正和说明。)
仅针对C标准中的形式语法,C 2018 6.7 1中显示的declaration产生式可能是declaration-specifiers init-declarator-listopt ;
。在那里,declaration-specifiers 可能会产生 storage-class-specifier declaration-specifiers opt 和 init-declarator-list 可能不存在,给出 storage-class-specifier 声明说明符opt ;
。那么后面的declaration-specifiers可能就没有了,给出storage-class-specifier;
,最终可以产生static
;
.
但是,C 标准的规则超出了语法范围。 C 2018 6.7 2 说:
A declaration other than a static_assert declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration.
声明 static
;
没有声明声明符、标记或枚举的任何成员,因此它违反了此约束。然后一个符合标准的 C 实现必须为它发出一个诊断消息,尽管它仍然可以接受它。
static
const
int
;
和long
int
const
typedef
long
;
也违反了这个约束。
此外,C 2018 6.7.2 2 说:
At least one type specifier shall be given in the declaration specifiers in each declaration,…
由于 static
;
没有类型说明符,例如 void
、int
或 long double _Complex
,它也违反了此约束。
static
const
int
;
和long
int
const
typedef
long
;
不要违反这个约束。
It seems like init-declarator-list in a declaration has been made explicitly optional. Is there any use for declarations without it?
是的,我们可以有用地声明结构、联合和枚举标记,如 struct foo { int x; };
中所示。这声明了类型 struct foo
并且没有 init-declarator(在主层;当然有一个嵌套在里面)。
我们也可以声明枚举常量,如struct foo { apple, banana };
。这在任何级别都没有 init-declarator。
事实上有一些有用的声明没有 init-declarator 意味着 init-declarator 必须在生产或生产必须分成两个生产,其中一个允许声明结构等没有 init-declarator 并且其中一个产生带有强制性 init 的声明-声明符。据推测,使语法表示复杂化的麻烦不值得减少语义约束的好处。
我在看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 似乎已明确设为可选。没有它声明还有用吗?
(这不是 C 标准;它是一个非官方草案。第 463 页是非规范性文本——它只是提供信息而不是标准的约束部分。这个答案使用官方 C 2018 标准,其中只有 2011 年标准的技术更正和说明。)
仅针对C标准中的形式语法,C 2018 6.7 1中显示的declaration产生式可能是declaration-specifiers init-declarator-listopt ;
。在那里,declaration-specifiers 可能会产生 storage-class-specifier declaration-specifiers opt 和 init-declarator-list 可能不存在,给出 storage-class-specifier 声明说明符opt ;
。那么后面的declaration-specifiers可能就没有了,给出storage-class-specifier;
,最终可以产生static
;
.
但是,C 标准的规则超出了语法范围。 C 2018 6.7 2 说:
A declaration other than a static_assert declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration.
声明 static
;
没有声明声明符、标记或枚举的任何成员,因此它违反了此约束。然后一个符合标准的 C 实现必须为它发出一个诊断消息,尽管它仍然可以接受它。
static
const
int
;
和long
int
const
typedef
long
;
也违反了这个约束。
此外,C 2018 6.7.2 2 说:
At least one type specifier shall be given in the declaration specifiers in each declaration,…
由于 static
;
没有类型说明符,例如 void
、int
或 long double _Complex
,它也违反了此约束。
static
const
int
;
和long
int
const
typedef
long
;
不要违反这个约束。
It seems like init-declarator-list in a declaration has been made explicitly optional. Is there any use for declarations without it?
是的,我们可以有用地声明结构、联合和枚举标记,如 struct foo { int x; };
中所示。这声明了类型 struct foo
并且没有 init-declarator(在主层;当然有一个嵌套在里面)。
我们也可以声明枚举常量,如struct foo { apple, banana };
。这在任何级别都没有 init-declarator。
事实上有一些有用的声明没有 init-declarator 意味着 init-declarator 必须在生产或生产必须分成两个生产,其中一个允许声明结构等没有 init-declarator 并且其中一个产生带有强制性 init 的声明-声明符。据推测,使语法表示复杂化的麻烦不值得减少语义约束的好处。