外部、内部且没有链接,或者为什么这不起作用?

External, internal and no linkage or why this does not work?

根据C标准:

In the set of translation units and libraries that constitutes an entire program, each declaration of a particular identifier with external linkage denotes the same object or function. Within one translation unit, each declaration of an identifier with internal linkage denotes the same object or function. Each declaration of an identifier with no linkage denotes a unique entity.

在我的示例中,我们有三个单独的声明,每个标识符都有不同的 linkage.So 为什么这不起作用?

static int a; //a_Internal

int main(void) {
    int a; //a_Local
    {
        extern int a; //a_External
    }
    return 0;
}

错误:

In function 'main': Line 9: error: variable previously declared 'static' redeclared 'extern'

为什么编译器坚持要我重新声明而不是尝试访问另一个文件中的外部对象?

可供参考的有效 C++ 示例:

static void f();
static int i = 0;               // #1
void g() {
  extern void f();              // internal linkage
  int i;                        // #2 i has no linkage
  {
    extern void f();            // internal linkage
    extern int i;               // #3 external linkage
  }
}

Clang 和 VC 似乎都适合我的 C 示例;只有某些版本的 GCC(不是全部)会产生上述错误。

编译器给出此错误是因为在 a_External 范围内,a_Internal 仍然可以访问,因此您将 a_Internalstatic 重新声明为 externa_External 中,因为 a 的名称冲突。这个问题可以通过使用不同的变量名来解决,例如:

static int a1; //a_Internal

int main(void) {
    int a2; //a_Local
    {
        extern int a3; //a_External
    }
    return 0;
}

C 标准说:

In the set of translation units each declaration of a particular identifier with external linkage denotes the same entity (object or function). Within one translation unit, each declaration of an identifier with internal linkage denotes the same entity.

在翻译单元集中,我们不能有多个同名的不同外部实体,因此表示单个外部实体的每个声明的类型应该一致。我们可以检查类型是否在一个翻译单元内一致,这是在编译时完成的。我们无法在编译时或 link 时检查不同翻译单元之间的类型是否一致。

For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage.

static int a; //a_Internal

int main(void) {
    int a; //No linkage
    {
        extern int a; //a_External
    }
    return 0;
}

这里前面声明的标识符a没有linkage,所以extern int a有外部linkage。这意味着我们必须在另一个翻译单元中定义 int a 。但是 GCC 决定拒绝此代码,其中变量先前声明 static 重新声明 'extern' 错误,可能是因为根据 C 标准我们有未定义的行为。

§6.2.2,7 说:

If, within a translation unit, the same identifier appears with both internal and external linkage, the behavior is undefined.

因此,您的程序有 undefined behaviour

§6.2.2,4 表示

extern int a; //a_External

具有外部链接,因为在范围 int a; //a_Local 中可见的先前声明具有 无链接。但是

static int a; //a_Internal

声明 a 具有内部链接。因此,它是 undefined 每 §6.2.2, 7.