C中暂定定义的解释

时间:2014-07-16 13:54:50

标签: c c99

假设我有两个源文件:main.ca.c

main.c

#include <stdio.h>

int a;

int i;
int i;

int main(void)
{
    printf("a = %d\n", a);
    printf("i = %d\n", i);

    return 0;
}

a.c

int a;

然后,根据最新的C99草案6.9.2 外部对象定义 p。 2(强调我的):

  

具有文件范围的对象的标识符声明   没有初始化程序,没有存储类说明符或没有   存储类说明符static构成暂定   定义。如果翻译单元包含一个或多个暂定   标识符的定义,翻译单元包含 no   对于该标识符的外部定义,那么行为就是完全正确的   好像翻译单元包含一个文件范围声明   标识符,在翻译结束时使用复合类型   单位,初始化程序等于0。

编译(未给出警告):

gcc -g -std=c99 -pedantic-errors -Wall -Wextra main.c a.c

我理解,对于i变量,有两个是暂定定义,因为main.c没有“真正的”外部定义,所以它们被合并到这样的定义中。那么a呢?我是否正确说明,暂定定义不是在多个源文件(即翻译单元)之间“共享”的?

1 个答案:

答案 0 :(得分:6)

您的程序错误:它多次定义相同的外部名称。 GNU工具链遵循宽松的链接模型,该模型不会将此标记为错误;它合并了多个定义。但是,这实际上是语言扩展。严格符合ISO C程序不能多次定义名称。

&#34;暂定定义的概念&#34;在一个翻译单元内是纯粹的句法。在翻译单元的最后,任何仍然是暂定的定义都会被固定。#34;作为定义。

调用int i;的原因&#34;暂定&#34;它是&#34;弱&#34;从某种意义上说。它可以被后来的定义覆盖。如果在翻译单元结束时,它不会变为int i = 0

所以例如这是有效的:

int i;  /* might become int i = 0 */

int i = 42; /* i is now defined; the tentative definition is replaced */

在这种情况下,i被理解为定义一次,而不是两次。翻译的单元包含i的单一定义。