【发布时间】:2011-03-10 04:39:22
【问题描述】:
在我看来,即使我在没有 extern 声明的情况下引用另一个文件中的函数,gcc 仍然可以编译该单元。所以我想知道在函数的任何地方是否都需要 extern 声明?我知道你需要 extern 作为变量。
【问题讨论】:
在我看来,即使我在没有 extern 声明的情况下引用另一个文件中的函数,gcc 仍然可以编译该单元。所以我想知道在函数的任何地方是否都需要 extern 声明?我知道你需要 extern 作为变量。
【问题讨论】:
函数默认具有外部存储类说明符(除非它们明确定义为静态)
extern Storage Class Specifier
如果声明描述了一个函数或出现在函数之外并描述了一个具有外部链接的对象,则关键字 extern 是可选的。如果不指定存储类说明符,则假定该函数具有外部链接。
....
由于声明不兼容,在没有存储类说明符的声明之前包含具有存储类说明符 static 的同一函数的声明是错误的。在原始声明中包含 extern 存储类说明符是有效的,并且函数具有内部链接。
【讨论】:
这不是必需的,但我更喜欢在标题中使用它来强化这个函数在其他地方定义的想法。
对我来说,这是:
int func(int i);
是稍后需要的函数的前向声明,而这个:
extern int func(int i);
是一个将在此处使用但在其他地方定义的函数的声明。
这两行在功能上是相同的,但我使用extern 关键字来记录差异,并与常规变量保持一致(其中差异很重要,并且完全具有该含义)。
【讨论】:
const 或最多一个参数。这还取决于您认为“太多”的参数数量。
ints,而不是在 C99 中,则不正确。
对于变量,您不一定“需要”extern。
当 C 被发明时,也编写了 Unix 链接器,它们以不为人知但聪明的方式推进了艺术。一项贡献是将所有符号定义为小的“公共块”。这允许声明的单一语法,而无需指定哪个模块正在分配空间。 (实际上只有一个模块可以初始化对象,但不需要任何人。)
确实有三个考虑因素。
原型的前向声明。 (可选,因为旧版 C 必须在没有它们的情况下进行编译。)
除一个文件外,所有文件中的非函数对象(变量)的外部声明。 (仅在也具有糟糕链接器的非 Unix 系统上需要。希望现在这种情况很少见。)
对于函数,如果不存在函数体来形成定义,则 extern 已经是假设。
【讨论】:
ld(1) 可以为每个符号做一个。
据我所记得的标准,默认情况下所有函数声明都被视为“外部”,因此无需明确指定。 这不会使这个关键字无用,因为它也可以与变量一起使用(在这种情况下 - 它是解决链接问题的唯一解决方案)。但有了这些功能 - 是的,它是可选的。
更详细一点的答案是,它允许您使用在另一个源代码文件中编译的变量,但不为变量保留内存。因此,要使用 extern,您必须有一个源代码文件或一个库单元,其中包含顶层变量(而不是函数内)的内存空间。现在,您可以通过在其他源代码文件中定义同名的 extern 变量来引用该变量。
一般来说,应该避免使用外部定义。它们很容易导致难以管理的代码和难以定位的错误。当然,也有其他解决方案不切实际的例子,但它们很少见。例如,stdin 和 stdout 是映射到 stdin.h 中 FILE* 类型的外部数组变量的宏;此数组的内存空间位于标准 C 库单元中。
【讨论】: