2

我正在尝试基于 extern 的程序,据我所知,这在访问只有一个定义的多个文件中的变量时很有帮助。

但是我尝试了一个简单的程序,如下所示extern,当我预计它会在链接过程中失败时,事情似乎可以正常工作

文件5.c:

#include <stdio.h>
#include "var.h"

int a = 20;

int main() {
  printf("\n File5.c a = %d", a);
  test();
  return 0;
}

文件6.c:

#include <stdio.h>
#include "var.h"

int test() {
  printf("\n File6.c a = %d",a);
}

变种h

int a;

由于我已包含var.h在所有没有外部的头文件中,int a因此将包含在.c文件中和链接期间,编译器应该会抛出警告或错误消息,但它编译文件时没有任何问题。

不应该var.h有以下extern int a吗?

4

1 回答 1

2

标题通常最好使用extern int a;. 另请参阅如何在 C 中的源文件之间共享变量?

标准说:

ISO/IEC 9899:2011 §6.9.2 外部对象定义

语义
¶1如果对象标识符的声明具有文件范围和初始化程序,则声明是标识符的外部定义。

¶2具有文件范围的对象的标识符声明没有初始化程序,并且没有存储类说明符或具有存储类说明符static,构成一个 暂定定义。如果翻译单元包含一个或多个标识符的暂定定义,并且翻译单元不包含该标识符的外部定义,则行为与翻译单元包含该标识符的文件范围声明完全相同,复合类型为翻译单元的末尾,初始化器等于 0。

因此,标题中的内容是变量的暂定定义。在 的翻译单元 (TU) 末尾file5.c,您不再有暂定定义;指定的“外部定义”int a = 20;已指定。在 TU 的末尾file6.c,您有一个等效于 的定义int a = 0;

当您尝试链接file5.candfile6.c时,您应该遇到a. 然而,有一个共同的扩展,记录在附件 J 的标准中:

J.5.11 多个外部定义

¶1 对象标识符可能有多个外部定义,无论是否显式使用关键字extern; 如果定义不一致,或者不止一个被初始化,则行为未定义(6.9.2)。

您的编译器提供了 §J.5.11 标识的扩展,因此(合法地)不会抱怨。

580

于 2013-09-07T20:13:43.823 回答