【问题标题】:extern variable definition in other file其他文件中的外部变量定义
【发布时间】:2015-09-30 11:10:20
【问题描述】:

您好,我有以下 2 个文件 在a.c我有

#include <stdio.h>

int i;
static int j;
int main()
{
        printf("i = %d\n",i);
        printf("j = %d\n",j);
        return 0;
}

b.c 我有

#include <stdio.h>

extern int i=2;
extern int j=5;

在此示例中,当我运行时,我得到的答案为 2,0,但编译器对两个变量都抛出警告 initialized and declared ‘extern’

由于j 的范围仅适用于a.c,b.c 如何能够访问j 而不会引发错误?

【问题讨论】:

  • 请参阅other answers 这个问题。警告本身与a.c 无关。即使你自己编译b.c,你也会得到同样的警告。
  • 为什么说“j 的范围仅适用于 a.c”?它在 b.c 中声明为 extern
  • 由于ja.c 中被声明为静态,我认为范围仅限于该文件。
  • @arya 是的。这就是为什么你的主要打印0j 而不是5。不清楚你真正要问的是什么。
  • 好吧,让我这样说,当我在 b.c 中声明 static int j=0 并在 a.c 中声明 extern 并在 @ 的 main 函数中打印 j 的值987654345@ 然后我得到链接器错误为undefined reference to j'`。那么反之亦然也应该这样做。对吧?

标签: c linux static extern


【解决方案1】:

首先,在将变量声明为 extern 的同时初始化变量没有任何意义。这就是您收到编译器警告的原因。如果变量在文件范围内,C 允许这样做,但与往常一样,C 允许许多不好的事情。

还要注意,使用 extern 几乎总是不好的做法,应该避免。

现在对于代码,i 的行为符合预期,因为两个文件中的 i 引用同一个变量。另一方面,jstatic,因此该变量的范围缩小到本地文件。标准中有一条规则说所有静态变量必须初始化为 0,除非程序员显式初始化它们。所以j的值为0。

由于j 是静态的,extern int j; 指的是“其他地方的另一个 j”,因为在您编写 extern 的文件中没有可见的 j 变量。由于程序没有使用“其他地方的另一个 j”,因此该变量将被丢弃。

staticextern 在很多方面都是对立的。如果您认为同时声明同一个变量 static 和 extern 有意义,则需要更多地研究 static 关键字。

【讨论】:

  • 这是一个面试问题,如果我这样做,编译器会如何表现?
【解决方案2】:

交流

#include <stdio.h>
int i;
static int j;
extern void display();
int main()
{
        printf("i = %d\n",i);
        printf("j = %d\n",j);
        display();
        return 0;
}

b.c

#include <stdio.h>
extern int i;
extern int j;

void display()
{
     printf ("%d",j);
}

c.c

#include <stdio.h>
extern int i=2;
extern int j=5;
void display()
{
   printf ("%d",j);
}

如果你编译 a.c 和 b.c GCC 会报错

对“j”的未定义引用。

因为程序试图访问未定义在 b.c 范围内的 j

如果你编译 a.c 和 c.c GCC 会像你所说的那样抛出警告

警告:âjâ 已初始化并声明为âexternâ

并假定在 c.c 中定义的 j 不会抛出任何错误。

在您的情况下,如果您在 b.c 中删除分配,您在编译时不会发现任何错误,因为在 b.c 中没有访问 j 值的函数。

【讨论】:

    【解决方案3】:

    static 数据默认使用0 初始化,如果没有另外说明,这就是为什么你得到 0 作为答案,它与 b.c 模块无关。此外,不能同时声明 staticextern 的变量,这对我来说听起来很矛盾。

    当使用extern 时,您应该只声​​明一个变量(没有设置空间来保存它在内存中),该变量的定义将在其他模块中。 extern 以一种简单的方式告诉编译器,嘿,不要担心它在模块的其他地方定义的这个变量,所以不要为它设置任何空间。

    为什么你的编译器没有抛出错误? b.c 在你的程序中是否与 a.c 相关联?尝试这样做,看看会发生什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-03
      • 1970-01-01
      • 2023-04-08
      • 2014-11-13
      相关资源
      最近更新 更多