了解外部存储类

这个问题在这里已经有了答案:

  • 定义和声明有什么区别? 25个答案

  • 变量a被声明并定义为行中的全局变量

    int a = 20;
    

    extern行只是告诉main()函数的作用域, a是在另一个地方定义的。

    在这种情况下,使用extern并不是真的必要。 您可以在main()函数之前声明并定义a ,然后main()会熟悉它。

    通常,当你想使用在另一个源文件中定义的变量或函数时(而不仅仅是在相同的源文件中),你可以使用extern


    extern在语法上是一个“存储类”关键字。 但是没有这样的存储类。 C有“静态存储”,“动态存储( malloc等)和”自动存储“(局部变量,通常用堆栈表示)。

    如果标识符在块范围内声明为extern ,则表示该声明引用了外部定义。 如果被声明的实体是一个对象,那么它就具有静态存储,只是因为外部对象具有静态存储。 它也可以是一个功能; 函数不被认为具有存储。

    在C中,有一个叫做“连接”的概念。 在文件范围外的任何函数之外声明的对象和函数可以具有“外部”或“内部”链接。

    如果我们在块范围内有extern ,就像在示例程序中一样,可以在文件范围或嵌套范围内预先声明相同的名称,如下所示:

    static int x;
    
    /* ... */
    
      {
        extern int x;
      }
    

    在这里,内部x是指外部x ,尽管是“外部”,但由于“静态”而具有内部联系。

    简而言之, extern通常意味着“引用先前的声明,如果没有声明,则将其声明为具有外部链接的标识符”。

    “外部”这个词指的是两个单独的概念:前面提到的“外部联系”,也指“任何功能之外”的意思,如在“外部声明”中。 令人困惑的是,“外部声明”,如上面的static int x ,可以有“内部联系”!

    在你的程序中,事情是正确的,因为块范围extern声明a和后面的int a = 20 ,它们在不同的范围内,恰好相互独立。

    int a = 20; 是一个外部声明,它也是一个外部定义(由于初始化器)。 由于在该范围内,没有事先声明a是可见的,它得到外部链接。

    因此,其中a定义? 它在整个翻译单元中被定义为具有外部链接的对象。 翻译单位是什么定义aa在声明出现的程序的每个地方声明; 其定义也是一个声明。 它在main以及翻译部门源代码的最后一行中进行了声明。

    “声明”是使某个名称在某个范围内已知的语法。 这是一个在翻译节目时积极的概念。 “定义”是在某翻译单位中提供了一些对象或功能。 翻译过的单位仍然提供定义,但不需要保留关于声明的信息。 (这就是为什么当我们创建库时,我们提供头文件和其中的声明!)

    从你main功能的角度来看,这个功能并不关心a的定义。 它已宣布a以这样的方式,如果a被使用,那么外部定义a与外部连接,必须存在。 该定义可能来自任何地方:可能位于同一翻译单位或另一翻译单位。


    C编程语言被设计为一次通过,因此编译器只能从上到下处理每行一次。 所以考虑你的程序:

    #include <stdio.h>
    
    int main(){
       extern int a;
       printf("%dn",a);
       return 0;
    }
    
    int a = 20;
    

    标识符a被声明两次,并定义一次。

    在第四行之前extern int a; ,编译器不知道关于标识符a任何信息。 声明extern int a; 在函数main具有块范围,并将标识符a声明为int ,并且其存储持续时间是静态的,并且链接是外部的。 因此,编译器可以编写代码,通过名称a访问全局标识符,作为可以在另一个模块(外部链接)中定义的int变量。 这是编译器在printf使用的第5行。

    最后在第9行, int a = 20; 是另一种声明和定义。 这声明和定义a一个具有静态存储持续时间的int ,以及外部链接。

    如果你把int a = 20;main之前,声明extern int a; 将是无用的,因为它不会添加任何东西。 我倾向于将我的main函数和其他依赖函数放在我的源代码中,这样只需要最少量的额外声明。

    链接地址: http://www.djcxy.com/p/40629.html

    上一篇: understanding of extern storage class

    下一篇: In C language head file