【问题标题】:Using a variable in a file with extern keyword which is defined as static as well as global in the base file?在具有 extern 关键字的文件中使用变量,该变量在基本文件中定义为静态和全局?
【发布时间】:2020-07-04 13:07:29
【问题描述】:

我们可以在文件中使用 extern 来使用在基础文件中定义为静态和全局的变量吗?

【问题讨论】:

  • 我不认为我理解这个问题。能举个例子吗?

标签: c static extern storage-class-specifier


【解决方案1】:

您不能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 不声明具有外部链接的链接标识符:它(重新)声明具有其先前链接的标识符(外部内部),除非之前没有这样的声明或声明没有链接(非静态本地没有链接)。

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?
    
}

【讨论】:

  • 对于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 都符合,因为任何事情都可以。
  • 好的。谢谢你的解释。不过,由于语言冲突,这个 UB 令人失望。另一个 UB 实例不买任何速度,并且在编译时完全可以预防。
  • @EricPostpischil 谢谢。我已将您的信息编辑到答案中。
猜你喜欢
  • 1970-01-01
  • 2012-06-22
  • 2015-11-24
  • 1970-01-01
  • 2012-10-25
  • 1970-01-01
  • 2020-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多