【问题标题】:"extern" inside a function?函数内部的“外部”?
【发布时间】:2012-08-25 08:17:33
【问题描述】:

好吧,阅读“有点老”的书(“The C 编程语言”,第二版,Dennis Ritchie 着),我遇到了以下问题:

外部变量必须在任何函数之外定义一次;这为其预留了存储空间。该变量也必须在每个想要访问它的函数中声明

我当时想 - 什么?!

“该变量也必须在每个想要访问它的函数中声明”。然后,我又震惊了一次:

int max; 
/* ... */
int main()
{
    extern int max;
    /* ... */
}

还有一个 - 什么?!


据我所知(显然,这还远远不够),extern 仅在您在某处定义全局变量并且您想通过另一个文件访问它(而不是再次定义它)时才有意义。

所以:

  • extern int max main 或任何其他函数有什么意义?
  • 标准真的说这是一个必须吗(我需要在每个例子中声明这个max函数,那会用吗?)
  • 这对于 C++ 是否相同(这就是我放置 C++ 标记的原因)?这是我第一次看到这样的东西。

注意:这和What is the use of declaring a static variable as extern inside a function?不一样

【问题讨论】:

  • Amazon.com 说 K&R 第 2 版。于 1988 年出版。我猜从那时起标准已经发生了一些变化。 :)
  • 是的,我知道出版年份,这就是我的想法,但我想问一下,只是为了确定。这就是我要求 ISO 标准确认的原因。
  • @KirilKirov 您需要 C 或 C++ 标准的引用吗?
  • 我认为这一切都在当年用 ANSI C /C89 解决了。
  • @Kiril Kirov 您必须阅读接下来的段落(以及整章),这应该可以消除您的困惑。例如“如果外部变量的定义在源文件中出现在特定函数中之前,则不需要在函数中声明外部变量。”这一章是教你一些关于链接和范围的知识,它通过简单的例子来做到这一点,不一定是最佳实践。

标签: c++ c global-variables extern kernighan-and-ritchie


【解决方案1】:

你的帖子让我吃惊。我不记得了,我很久以前就读过 K&R。我这里只有第一版,它也在那里。然而,这并不是它所说的全部。从第一版开始:

变量也必须在每个想要的函数中声明 访问它;这可以通过显式的外部声明来完成 或根据上下文隐含。

注意“根据上下文隐式”。正文后面:

...如果变量的外部定义出现在源文件中 在将其用于特定功能之前,则不需要 函数中的外部声明。主要的外部声明, ...因此是多余的。事实上,常见的做法是放置 源代码开头的所有外部变量的定义 文件,然后省略所有外部声明。

所以这就是说使 extern 变量可见可以在函数内部为该函数完成,或者可以在任何函数之外为源文件中跟随它的所有函数完成。我相信这是本书中唯一在函数内部完成的地方,后来它使用熟悉的一次文件方法。

【讨论】:

    【解决方案2】:

    extern int max inside main or function 对编译器说“我不是 main 或函数内部的局部变量,我是其他地方定义的全局变量”

    如果全局在同一个文件中声明,则无用。在不同的文件中,是的,但不是在每个函数中,只需在使用此全局变量的源的头文件中声明一次。在c++ 中也是如此。

    【讨论】:

      【解决方案3】:

      extern链接。这意味着此名称max 链接到该名称的其他出现,可能在其他文件中。 (也就是说,当对象模块链接在一起形成一个可执行文件时,所有对该名称的链接引用都将指向同一个对象。)

      这个声明的范围是它所在的函数体的剩余部分。这意味着这个文件中的其他函数看不到这个声明所声明的名称(除非它们自己声明)。

      范围和链接是不同的东西。

      【讨论】:

      • 即使在 K&R 2ed 中,也没有必要在此示例中使用 extern。 “在某些情况下,可以省略 extern 声明。如果外部变量的定义在源文件中出现在特定函数中之前,则不需要在函数中声明 extern。” int max 的第一个实例将被视为声明。
      • 函数内部可能不需要使用extern int max,但是,如果函数内部存在int max,则必须使用extern。否则,int max 在函数内部单独声明一个没有链接的新自动对象。会和外部的max不同。
      猜你喜欢
      • 2018-06-12
      • 2018-09-11
      • 1970-01-01
      • 1970-01-01
      • 2012-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      相关资源
      最近更新 更多