【问题标题】:Benefits of using extern declaration in same file as definition?在与定义相同的文件中使用外部声明的好处?
【发布时间】:2016-05-19 12:27:43
【问题描述】:

我正在阅读一个 C 项目的源代码,并试图找出为什么要使用 extern 的特定用法。 (注意:This question 是相关的,但对于 C++,而不是 C。)假设我有四个头文件,每个头文件都声明一个 extern const 结构:

extern const struct puppy fido;

这个结构体在源文件中定义如下:

extern const struct puppy fido;
static const struct puppy *puppies[] = { &fido };
const struct puppy fido = { "fido", 10, 10 };

当这些变量在同一个源文件中定义时,在源文件中将变量声明标记为extern 是否有某种好处?

【问题讨论】:

  • 我认为这篇文章可能会有所帮助:stackoverflow.com/questions/1433204/…
  • 请澄清一下,我是否理解正确:您有 4 个带有 extern 声明的头文件,以及 1 个包含 extern 声明和定义的 .c 文件?
  • @Lundin 没错。
  • fido 是否在 ... 中被引用?
  • @M.M 是的,我已经更新了问题。

标签: c


【解决方案1】:

唯一的好处是声明和定义之间的任何代码都可以访问该变量。除此之外,同一个文件中的 extern 声明毫无意义。

【讨论】:

  • 我认为无论如何都不需要extern。但它确实看起来像一个“前向声明”。
  • 另外,有些人认为将文件中所有静态变量的声明放在靠近顶部的位置是很好的代码组织,即使没有特定原因需要“前向声明”
  • 虽然声明允许在定义之前访问变量,但它没有回答有关在声明中使用extern的问题。
【解决方案2】:

Lundin 是正确的,在这种情况下 extern 不会影响 fido 在其他源文件中的可见性。在您的示例代码中,它用作前向声明。

C99 标准的相关部分,第 6.2.2 节:

4) 对于使用存储类说明符 extern 在该标识符的先前声明可见的范围内声明的标识符,如果先前声明指定内部或外部链接,则后面声明的标识符的链接是与先前声明中指定的链接相同。如果前面的声明不可见,或者前面的声明没有指定链接,则标识符具有外部链接。

5) 如果函数标识符的声明没有存储类说明符,则其链接的确定与使用存储类说明符 extern 完全一样。对象的标识符具有文件范围且没有存储类说明符, 它的链接是外部的

在 C++ 中,行为会有所不同,因为使用 const 声明的变量隐式为 static。在C++中,需要在第一次声明变量时使用extern,否则其他编译单元找不到。

C++98 标准,第 3.5.3 节:

具有命名空间范围 (3.3.5) 的名称如果是以下名称,则具有内部链接

——显式声明为静态的对象、引用、函数或函数模板,或者,

——显式声明为 const 且既未显式声明 extern 也未先前声明具有外部链接的对象或引用;

【讨论】:

  • FWIW,声明没有静态的内部变量在 C11 中被标记为一个过时的特性。C11 6.11.2 标识符的链接:“在没有静态存储类说明符的文件范围内声明具有内部链接的标识符是一个过时的功能。”
  • 这是一道C题,你为什么老说其他语言
  • @M.M 将来有人可能会搜索这个,却没有意识到 C 和 C++ 以不同的方式工作。
【解决方案3】:

有时,当您编写源文件时,您只需要头文件的一部分,而不是全部。

在源文件中重复 extern 声明允许您不在该特定源文件中包含头文件。

这不一定是一个好习惯。

【讨论】:

    【解决方案4】:
    extern const struct puppy fido;
    // ...
    const struct puppy fido = { "fido", 10, 10 };
    

    如果const struct puppy fido = { "fido", 10, 10 }; 在 2 个不同的 .c 文件中编译,它将失败。在const struct puppy fido = { "fido", 10, 10 }; 之前和之后应该有#ifndefendif,以便包含一次。

    一个良好的做法(通常必须避免使用全局变量)是在 .h 文件中使用 extern 声明,并将变量的定义放在 .c 文件中。

    【讨论】:

    • ifndef/endif 对涉及跨 2 个不同 c 文件的编译问题没有帮助。我不确定你想说什么
    • @M.M :假设在 c 文件中您使用#define DECLARE_MY_CONST_FIDO,然后包含此标头。 const struct... 将仅写入此文件。如果const声明在没有#ifdef DECLARE_MY_CONST_FIDO的文件中,如果文件包含在多个.c文件中肯定会失败。
    • 好的,可能在您的答案中包含示例代码。这是一种不寻常的技术,所以人们不会知道你在说什么
    猜你喜欢
    • 2020-04-22
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多