C11 在第 6.7 节中指定了哪些声明也是定义:
标识符的定义是该标识符的声明,它:
— 对于对象,导致为该对象保留存储;
[...]
我没有找到哪些对象声明导致存储被保留的完整列表。 直觉上我很清楚,但我无法从 C11 标准中获取这些信息。
没有明确的列表,因为标准只是描述了什么是定义,而不是在一个地方。我将尝试在这里总结一下。为了保持一致性,我将在这里只使用没有任何限定符(如const
(的类型int
。
-
如果将初始值设定项添加到声明,则它始终是一个定义:
int x = 1;
-
如果没有初始值设定项,以下是它们在函数作用域中的定义:
int x; auto int x; // auto is the default anyways register int x; // register is just a hint, but would be "storage" as well static int x; // also reserves storage, but with static duration
-
在文件范围内,规则稍微复杂一些;以下是暂定定义:
int x; static int x;
标准(§6.9.2p2(的措辞是:
具有文件范围而不带初始值设定项的对象的标识符声明,以及 如果没有存储类说明符或带有存储类说明符
static
,则构成暂定定义。如果翻译单元包含一个或多个暂定定义 标识符,并且翻译单元不包含该标识符的外部定义,则 该行为与翻译单元包含的文件范围声明完全相同 标识符,具有截至翻译单元末尾的复合类型,带有初始值设定项 等于 0因此,这意味着如果发现它们引用另一个定义,它们最终会">成为定义"。
-
使用存储类
extern
且没有初始值设定项,则没有定义:extern int x; // <- not a definition
AFAIK,这应该是完整的规则集。如果我忘记了什么,请随时编辑/评论。