【问题标题】:If a variable with internal linkage is referenced in a block, do I need to use the extern keyword in that block?如果在块中引用了具有内部链接的变量,我是否需要在该块中使用 extern 关键字?
【发布时间】:2020-09-15 03:36:33
【问题描述】:

我试图在范围和链接的上下文中确定变量声明的所有细微差别。

考虑以下两个sn-ps代码:


代码 1 阻止 extern 声明

#include <stdio.h>

static int i=4;

int main()
{
  {
    i++;
    printf("i is %d \n",i);
    i++;
  }
  printf("i is %d \n", i);
  i++;
  printf("i is %d \n", i);

  return 0;
}

输出是:

i is 5
i is 6
i is 7

代码 2 阻止 extern 声明

#include <stdio.h>

static int i=4;

int main()
{
  {
    extern int i;
    i++;
    printf("i is %d \n",i);
    i++;
  }
  printf("i is %d \n", i);
  i++;
  printf("i is %d \n", i);

  return 0;
}

输出是:

i is 5
i is 6
i is 7

鉴于这两个代码 sn-ps 生成相同的输出,我将假设它们在“幕后”以相同的方式运行(即编译器生成相同的结果可执行文件)。

那么问题来了:

代码 2 是否只是执行代码 1 的一种“礼貌”、用户友好的方式(即,您要通知读者,“嘿……这个变量 i 已在其他地方定义这个文件”?)。那么extern以这种方式使用是否只是满足某种约定?

【问题讨论】:

  • 代码 2 对i 进行了不必要的(重新)声明。许多程序员会认为它没有帮助。通常,您不应在函数内声明 extern 变量。有一个 GCC 警告 -Wnested-externs 选项来警告嵌套的 extern 声明 - 即函数内部的 extern 声明。
  • @JonathanLeffler 啊哈。很高兴知道。我问的唯一原因是因为在我的《C Programming: A Modern Approach》一书中,作者在谈论变量声明时多次使用代码 2-esque 示例(例如第 463 和 465 页)
  • 金先生的书?这是一本很不错的书。理论上,您应该知道函数内部的extern 是什么意思,但这仍然是值得商榷的做法。我认为所有这样的声明——函数或变量——都是不可取的,即使语言允许它们。 GCC 有支持我的偏见的选项,尽管默认情况下它们没有启用。

标签: c variables scope linkage


【解决方案1】:

在您的示例中,extern 声明没有添加任何内容。无论有无该声明,都会引用名为 i 的同一变量。

在块范围内声明extern 的示例如下:

#include <stdio.h>

int i=4;

int main()
{
  int i=0;
  {
    extern int i;
    i++;
    printf("i is %d \n",i);
    i++;
  }
  printf("i is %d \n", i);
  i++;
  printf("i is %d \n", i);

  return 0;
}

在这种情况下,一个名为i 的变量具有块作用域并且没有链接,它掩盖了具有文件作用域和外部链接的同名变量。然后在内部范围内,extern 声明使i 引用文件范围内的变量。

此代码然后输出:

i is 5 
i is 0 
i is 1 

另请注意,在这种情况下,文件范围内的 i 不能是 static。这是因为extern 声明查看具有给定名称的最里面的变量以确定标识符的链接。如果前面的声明没有链接,那么extern 声明是指具有外部链接的变量。这将与声明为static 的文件范围变量冲突。

这在C standard 的第 6.2.2p4 节中有详细说明:

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

【讨论】:

  • 当然,这样的代码本身就是可憎的(尽管它是有效的 C 代码)。 GCC 有 -Wshadow 选项来报告局部变量隐藏更接近全局变量的位置。它会适合您的示例代码。
  • @dbush 感谢您提供的示例。但是,我在理解您的最后一段时遇到了一些麻烦(当您解释为什么变量 i 被声明为外部链接时,如果相反,它被声明为内部链接......其他一切都保持不变。 ..会无效)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-27
  • 2015-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-22
相关资源
最近更新 更多