【发布时间】:2020-07-04 13:07:29
【问题描述】:
我们可以在文件中使用 extern 来使用在基础文件中定义为静态和全局的变量吗?
【问题讨论】:
-
我不认为我理解这个问题。能举个例子吗?
标签: c static extern storage-class-specifier
我们可以在文件中使用 extern 来使用在基础文件中定义为静态和全局的变量吗?
【问题讨论】:
标签: c static extern storage-class-specifier
您不能extern-重新定义static 变量,尽管您可以extern-重新声明它。
错误:
//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 不声明具有外部链接的链接标识符:它(重新)声明具有其先前链接的标识符(外部或内部),除非之前没有这样的声明或声明没有链接(非静态本地没有链接)。
对于使用存储类说明符 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?
}
【讨论】:
int x = 1000;在main里面的例子,标准是没有歧义的,GCC和Clang都符合:在extern int x;里面,只有int x = 1000;的x是可见的,因为它隐藏了先前的声明,因此它是 6.2.2 所指的声明 4. 先前的声明 int x = 1000; 没有链接,因此新的 x 具有外部链接。然后 x 已声明为内部链接(由第一个 static int x = 42 和外部链接(由这个新链接),标准表示未定义行为,因此 GCC 和 Clang 都符合,因为任何事情都可以。