【问题标题】:How are extern variables defined?外部变量是如何定义的?
【发布时间】:2013-07-10 08:27:42
【问题描述】:

我对在 C 中将 extern 关键字与变量一起使用有一些疑问。我确实浏览了与此问题相关的链接。不过还是有几样东西我没收集好

#include<stdio.h>
    main( )
    {
    extern int i;
    printf ( "\n%d ",i) ) ;
    }
    int i = 31 ;

在上面的代码中,我如何在它的定义语句之前打印出来?
现在在以下代码中:

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

语句不是“i=20;”吗?定义声明?我收到一个错误。是因为我试图更改在其他源文件中定义的变量吗?如果是这种情况,语句“int i=31;”如何?在最上面的代码sn -p 使用权吗?

另外,我读到“int i;”是一个定义。我真的不知道怎么做。

【问题讨论】:

    标签: c declaration definition extern


    【解决方案1】:

    在您的第一个程序中,打印语句根据extern int i 声明打印i 的值。这类似于根据原型声明调用函数而不查看其定义。编译器生成代码以检索名为i 的全局变量中的值。该符号在链接时被解析为正确的变量和地址。

    在您的第二个程序中,没有提供i 的定义,仅提供extern int i 声明,并尝试使用i = 20 设置其值。在链接时这会失败,因为没有定义,因此解析对全局变量的引用的尝试失败。将i = 20 更改为int i = 20 会在函数main() 的范围内创建一个名为i 的局部变量,并且不再引用全局声明的extern int i

    int i;在全局范围内使用时,它被视为一个声明并且可以被视为一种定义。使用初始化器声明的全局变量,例如:

    int i = 20;
    

    始终被视为定义。仅允许此类型的一个定义,即使每个定义都使用相同的初始值设定项。然而,

    int i;
    

    被视为声明。如果出现多个这些声明,则它们都被视为同一变量的声明。同时,如果不存在带有初始化器的声明,则该变量将隐式定义为初始化器为 0,并且链接器将能够解析对它的引用。

    【讨论】:

      【解决方案2】:

      变量/函数的声明只是声明变量/函数存在于程序中的某个位置,但没有为它们分配内存。

      来到定义,当我们定义一个变量/函数时,除了声明的作用,它还为该变量/函数分配内存。

      所以在第一个程序中,main() 之外的int i = 31 定义了变量 i。然后,该变量仅在 main() 中声明为外部变量。因此该程序有效。

      在第2个程序中,没有在别处定义变量i,直接声明为extern变量。因此它给出了一个错误。

      【讨论】:

        【解决方案3】:

        在第二个程序中,您没有在任何地方定义变量,而不是在 main 之外,而是在 main 中定义了它,所以您会收到该错误。

        但是在第一个程序中,您只定义了一次变量,并且在主程序之外,因此您不会收到该错误。程序在主程序之外查找并找到它的定义。

        int i; 是一个变量定义声明,既适用于 AUTO 变量(即在 main 或任何函数内),但不适用于 extern 变量的外部变量,您必须像这样声明它:

        extern int i;

        然后像这样定义外部main:

        int i;

        【讨论】:

          【解决方案4】:

          extern 背后的想法是您告诉编译器您将使用一个已经在使用范围之外定义的变量。

          在第二种情况下没有多大意义,因为 i 被定义为局部变量。 如果您将其定义为全局,就像您在第一种情况下所做的那样,那就没问题了。

          如果我可以用一个非常简单(人为的)案例来演示extern 的用法:

          main.c:

          #include <stdio.h>
          
          extern int a; /* we tell the compiler that a will come from outside the scope of where it is used */
          
          int main()
          {
              printf("%d\n", a);
          
              return 0;
          }
          

          source.c:

          int a = 3; /* we define a here */
          

          然后你像这样编译.c 文件:

          $ gcc main.c source.c
          

          这会输出3

          您可能还想阅读this 的文章。

          【讨论】:

          • 我相信两者都应该编译,但第二个将无法链接(启动 clang 来测试它
          • 好的,第一个示例编译失败,但不是因为变量声明 - 有一个多余的右括号...
          • @Christoph 第二个失败是因为说iextern 但实际上并没有同时使用它。注释掉所有涉及i 的行,将extern 一个,它会编译得很好。
          • @Christoph 只是仔细检查了一下,第一种情况是有效的,是的(在修复括号后),更新了我的答案,只提到了第二种情况。 i 是本地的,但他告诉链接器它是全局的。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-08-20
          • 1970-01-01
          相关资源
          最近更新 更多