在不同范围内使用具有相同标识符的多个静态变量的 extern

问题描述 投票:0回答:1

我正在阅读此处发布的以下问题#67418392

我很好奇如果 x 的前两个声明是使用静态(文件范围内的内部链接,块范围内没有链接)进行的,如下所示:

#include <stdio.h>

static int x = 50;

int main() {
    static int x = 10;

    {  
         extern int x;
         printf("inner block: %d\\n", x);

    }

    printf("outer block: %d\\n", x);
    return 0;

}

然而,GCC 给出以下错误(如果第二个

static int x=10;
被注释掉,该错误就会消失)。这是为什么?

<source>:10:18: error: variable previously declared 'static' redeclared 'extern'
10 |       extern int x;
   |                  ^

clang 或 msvc 没有编译器错误。这是为什么?

在上面的代码中,当你有语句时

extern int x;
它不应该使用前一个块中的声明,以便在运行时打印以下内容(这是我所期望的)

inner block: 10
outer block: 10

或者是因为块(主函数)内的静态变量没有链接,所以它使用文件范围内的静态变量?

使用 clang 编译时,它会显示以下内容:

inner block: 50
outer block: 10

来自#67418392的答案之一引用了C标准:

C 标准的

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

在示例代码中,文件范围内的静态变量在声明

extern int x;
的地方不可见,因为它被主函数中的静态定义所遮蔽(没有链接),因此根据标准
extern 
声明采取外部链接。在这种情况下,我们有
x
具有外部和内部链接,因此有未定义的行为?

c static extern
1个回答
0
投票

该错误发生在 GCC 中,因为它不允许将静态变量(具有内部链接)重新声明为 extern(假定外部链接)。然而,Clang 和 MSVC 通过允许 extern 声明引用文件范围变量来处理这种情况,并使用内部链接来处理它。这种差异会导致 GCC 抛出错误,而 Clang 和 MSVC 会产生预期的输出。

© www.soinside.com 2019 - 2024. All rights reserved.