首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解外部存储类

理解外部存储类
EN

Stack Overflow用户
提问于 2017-06-26 11:33:48
回答 5查看 243关注 0票数 2

你能给我解释一下下面问题的流程吗?

代码语言:javascript
复制
#include <stdio.h>

int main(){
   extern int a;
   printf("%d\n",a);
   return 0;
}

int a = 20;

输出是20。我不确定变量a是在哪里定义的,又是在哪里声明的?

EN

回答 5

Stack Overflow用户

发布于 2017-06-26 11:53:30

在下面的代码行中,变量a被声明并定义为全局变量

代码语言:javascript
复制
int a = 20;

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

在这种情况下,并不需要使用extern。您只需在main()函数之前声明和定义a,然后main()就会熟悉它。

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

票数 2
EN

Stack Overflow用户

发布于 2017-06-26 13:35:36

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

代码语言:javascript
复制
#include <stdio.h>

int main(){
   extern int a;
   printf("%d\n",a);
   return 0;
}

int a = 20;

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

在第4行extern int a;之前,编译器对标识符a一无所知。声明extern int a;在函数main内具有块作用域,它将标识符a声明为int,并且它的存储持续时间是静态的,链接是外部的。因此,编译器可以编写代码,通过名为aint变量来访问全局标识符,该变量可以在另一个模块(外部链接)中定义。这就是编译器在printf中使用时在行5上所做的事情。

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

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

票数 2
EN

Stack Overflow用户

发布于 2017-06-26 13:33:50

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

如果标识符在块范围内声明为extern,则意味着该声明引用了外部定义。如果被声明的实体是一个对象,那么它就有静态存储,这很简单,因为外部对象有静态存储。它也可以是一个函数;函数不是说有存储空间。

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

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

代码语言:javascript
复制
static int x;

/* ... */

  {
    extern int x;
  }

在这里,内部x指的是外部x,尽管它是“外部”的,但由于“静态”,它具有内部链接。

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

“外部”一词指的是两个不同的概念:前述的“外部联系”和“任何功能之外”的含义,如“外部声明”。令人困惑的是,“外部声明”,就像上面的static int x一样,可以有“内部链接”!

在您的程序中,事情是正确的,因为a的块作用域extern声明和后来的int a = 20处于不同的作用域中,它们恰好彼此独立地一致。

int a = 20;是一个外部声明,它也是一个外部定义(因为初始值设定项)。因为在该作用域中,先前看不到a的声明,所以它获得外部链接。

那么,a是在哪里定义的呢?它被定义为具有外部联系的对象,在整个翻译单位中作为一个整体。这个翻译单元就是定义a的单元。在程序中出现声明的每个地方都声明了a;它的定义也是一个声明。它是在main中声明的,也在翻译单元源代码的最后一行中声明。

“声明”是一种语法,它使名称在一定范围内为人所知。它是一个在程序翻译过程中活跃的概念。“定义”是在某些翻译单元中提供某些对象或功能的事实。翻译后的单元仍然提供定义,但不需要保留有关声明的信息。(这就是为什么当我们创建库时,我们提供带有声明的头文件!)

main函数的角度来看,该函数并不“关心”a是在哪里定义的。它声明a的方式是,如果使用a,则必须存在具有外部链接的a的外部定义。这个定义可以来自任何地方:它可以在同一个翻译单元中,也可以在另一个翻译单元中。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44752795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档