关于C#:了解extern存储类

understanding of extern storage class

本问题已经有最佳答案,请猛点这里访问。

你能不能请人给我解释一下下面这个问题的流程?

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

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

int a = 20;

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


变量a在行中声明并定义为全局变量:

1
int a = 20;

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

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

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


C编程语言被设计为一个过程,这样编译器就可以从上到下只处理每一行一次。所以考虑到你的计划:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

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

int a = 20;

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

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

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

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


是一个关键词的"存储类"。但没有这样的存储类。c Has"Static Storage","Dynamic Storage(EDOCX1&1)",and"Automatic Storage"(Local Varians,usually represented using a stack).

如果一个标识符是声明的extern,则在一个块的范围内,这意味着声明中提到一个外部定义。如果申报的实体是一个目标,那么它就有静态存储,简单,因为外部对象有静态存储。它也可以是一个功能;功能并不表示有存储。

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

如果我们有EDOCX1〕〔0〕的话,在一个块的范围内,如你有一个例子的程序,可以在文件范围内,或在一个狭窄的范围内,如:

1
2
3
4
5
6
7
static int x;

/* ... */

  {
    extern int x;
  }

在这里,内在的x参考外部的x,并且,在Spite of being"EXTERN",由于"Static"。

In a nutshell,externusually means"refer to the earlier declaration,and if there's no one,declara this as an identification with external linkage".

The word"external"refers to two separate concepts:the aforementioned"external linkage"and also to the meaning"outside of any function",as in"external declaration".混乱地,"外部声明",如同static int xAbove,can have"internal linkage"!

在你的节目中,事情是正确的,因为《埃多克斯宣言》1〔0〕〔9〕和后来的埃多克斯1〕10〔10〕,这两个节目都是在分隔的范围内进行的,因此是与其他节目中独立商定的。

这是一项外部宣言,也是一项外部定义(因为初始化)。从这个角度来看,没有任何先验的a宣言是显而易见的,它得到了外部链接。

那么,埃多克斯1〔9〕在哪里?它被定义为具有外部链接的对象,在整个翻译单元中作为一个整体。翻译单位是什么定义在该方案的每一个地方都宣布了一项宣言;它的定义也是一项宣言。它在main中宣布,并在翻译单位的最后一条源代码中宣布。

一个"宣言"是一个词汇,使某个范围内的一个名称成为众所周知。这是一个在一个程序翻译过程中活跃的概念。一个"定义"是一个事实,即在一些翻译单元中提供了一些对象或功能。Translated Units still provide definitions,but need not retain information about declarations.(Which is why we make libraries,we provide head files with declarations in them!)

From the point of the view of your mainfunction,that function doesn't"care"where ais defined.以这样一种方式,如果使用a则必须存在一个a的外部定义。定义可以从任何地方来:它可以在同一个翻译单元中,或者在另一个翻译单元中。


存储类extern指定标识符所指对象的存储持续时间和链接:

存储持续时间设置为静态,这意味着变量在程序运行的整个时间内都是活动的。当您声明函数范围内的变量时,这在您的示例中很重要,因为在函数范围内,默认的存储持续时间是自动的。

链接设置为外部,这意味着同一程序的不同翻译单元可以共享对象。它的副作用是另一个(文件)范围中的定义是可接受的,如您的示例所示。这是共享性质的逻辑结果,您通常会在所有使用它的翻译单元中声明具有外部链接的变量,但只在一个单元中定义它。


当您将变量声明为extern时,这意味着变量被声明为全局变量,并且不能在其中初始化变量。因为没有为该变量分配内存,所以它只是声明为变量。您可以在代码的某些位置定义它。

让我们举个例子..考虑一下代码

1
2
3
4
5
6
int main()
{
extern int i;
i=10;
printf("%d",sizeof(i));
}

这里有一个错误,int 'i' is not defined

因此,您需要将其写为:

1
2
3
4
5
6
int main()
{
    extern int i;
    int i=10;
    printf("%d",sizeof(i));
}

如果您的代码:这是声明

1
extern int a;

这是定义:

1
int a = 20;