1

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

考虑以下两个代码片段:


代码 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

带有 extern声明的代码 2

#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

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

所以这是一个问题:

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

4

1 回答 1

2

在您的示例中,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 

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

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

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

于 2020-09-15T03:45:38.387 回答