0

我们可以在使用 extern 的文件中使用一个变量,该变量在基本文件中既定义为静态又定义为全局?

4

1 回答 1

2

你不能extern-redefine 一个static变量,尽管你可以extern-redeclare 它。

错误的:

 //filescope
 static int x = 42;
 extern int x = 43; //WRONG

正确的:

 //filescope
 static int x = 42;
 extern int x; //redeclares the previous STATIC x (no linkage)

extern不使用外部链接声明具有链接的标识符:它(重新)使用其先前的链接(外部内部)声明标识符,除非之前没有这样的声明或声明没有链接(非静态本地有没有链接)。

6.2.2p4

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

不过,我不会尝试用复杂的遮蔽来推动这种行为,因为 gcc 和 clang 都不像内部静态的 extern-redeclarations 并且如果您在全局静态和最内部的重新声明之间有干预自动变量extern,那么最内部的标识符将有冲突的链接,这会导致按照6.2.2p7的未定义行为(感谢Eric Postpischil指出这一点)。

被 gcc 和 clang 接受:

#include <stdio.h>
static int x = 42;
extern int x;
int main()
{
    extern int x;
    printf("x=%d\n", x); //42
}

仅由 clang 接受(由于链接冲突,技术上是 UB)

#include <stdio.h>
static int x = 42;
extern int x;
int main()
{
    int x = 1000;
    printf("x=%d\n", x); //1000
    {
        extern int x; //conflicting (external) linkage
        //=> undefined behavior due to http://port70.net/~nsz/c/c11/n1570.html#6.2.2p7
        printf("x=%d\n", x); //42 on clang; compile time error on gcc
    }
}

也许奇怪的是不接受:

#include <stdio.h>
static int x = 42;
extern int x;
int main()
{
    static int x = 1000;
    extern int x;
    printf("x=%d\n", x); //1000?
    
}
于 2020-07-04T13:53:48.230 回答