C语言extern和static关键字详解


C语言extern和static关键字详解

文章目录

    • 1 前言
    • 2 作用域
      • 2.1 代码块作用域
      • 2.2 文件作用域
    • 3 存储类型
    • 4 链接属性
    • 5 extern和static关键字
      • 5.1 extern关键字
      • 5.2 static关键字

1 前言

  在讲extern和static关键字前,先讲几点相关的基础知识——作用域、存储类型、链接属性。这是几个相关性强,且容易混淆的概念。如果这几个概念理解了,再理解extern和static关键字的用法,就很容易。

2 作用域

  主要讲两个概念:代码块作用域和文件作用域。

2.1 代码块作用域

  位于一对花括号之间的所有语句称为一个代码块。任何在代码块的开始位置声明的标识符都具有代码块作用域,表示它可以被这个代码块中的所有语句访问,该代码块以外的任何语句都不可以访问它。

2.2 文件作用域

  任何在代码块之外声明的标识都具有文件作用域,它表示这些标识符从它们声明之处直到它所在的源文件结尾处都是可以访问的。在文件中定义的函数名也具有文件作用域,因为函数名本身并不属于代码块。

3 存储类型

  变量的存储类型是指存储变量值的内存类型。变量的存储类型决定变量何时创建、何时销毁以及它的值将保持多久。有三个地方可以用于存储变量:普通内存、运行时堆栈、硬件寄存器。这三个地方存储的变量具有不同类型。这里主要介绍前面两种。
  变量的缺省类型取决于它的声明位置。凡是在任何代码块之外声明的变量总是存储于静态内存中,也就是不属于堆栈的内存,这类变量称为静态(static)变量。我们无法为这类变量指定其他的存储类型。静态变量在程序运行之前创建,在程序的整个执行期间始终存在。
  在代码块内部声明的变量的缺省存储类型是自动的(automatic),也就是位于堆栈中,称为自动(auto)变量。当程序执行到声明自动变量的代码块时,自动变量才被创建,当程序离开代码块时,这些自动变量就被自行销毁。如果代码块被多次调用执行,那么自动变量将会被反复的创建和销毁。
  对于在代码块内存声明的变量,如果给它加上关键字static,可以使它的存储类型从自动变量变为静态变量。 如前面叙述,静态变量在整个程序执行过程中一直存在,就算代码块被反复调用执行,也不会被反复的创建和销毁。注意,修改变量的存储类型并不表示修改变量的作用域,它仍然只能在声明它的代码块的内部被访问。

4 链接属性

  当组成一个程序的各个源文件被编译后,所有的目标文件以及那些从一个或多个函数库中引用的函数链接在一起,形成可执行文件。然而,如果相同的标识符出现在几个不同的原文件中时,我们需要区分它们是否表示同一个实体。标识符的链接属性决定如何处理在不同文件中出现的标识符。
  链接属性一共有3中——external(外部)、internal(内部)和none(无)。没有链接属性的标识符(none)总是被当作单独的个体,也就是说该标识符的多个声明被当作独立不同的实体。属于internal链接属性的标识符只能为声明它的源文件所私有,其他源文件不可访问。位于多个不同源文件的多个声明属于不同的实体。最后,属于external链接属性的标识符不论声明多少次、位于几个源文件都表示同一个实体。例如:
C语言extern和static关键字详解_第1张图片
  上图中,标识符b和c的链接属性为external,其余标识符的链接属性为none。因此,如果另一个源文件也包含了标识符b类似声明或者调用函数c,他们实际上访问的是这个源文件所定义的实体。
  关键字extern和static用于在声明中修改标识符的链接属性。如果某个声明在正常情况下具有external连接属性,在它前面加上static关键字可以使它的链接属性变为internal。例如,如果第2个声明向下面这样写:
  static int b;
  那么变量b就将为这个源文件私有。当然,强调一下,static把链接属性变为internal的前提是它本来的链接属性为external。 如果该标识符的连接属性不为external,如变量e,对它用static修饰的时候,并没有把它的链接属性改为internal,仅仅是把它的存储属性改为了静态的。
  当然,我们也可以把函数声明为static,如下:
  static int c (int d);
  这样可以防止它被其他源文件调用。

5 extern和static关键字

5.1 extern关键字

  可以试着理解这样一句话,当一个标识符在声明时的链接属性为external,那么在其他文件中再对这个标识符声明时加上extern修饰,则extern修饰的这个标识符和最初的具有external连接属性的标识符为同一个实体,并可以对其进行操作。
C语言extern和static关键字详解_第2张图片
  上图为一个extern的使用示例。file1.cpp需要访问file2.cpp中定义的变量时,需要在file1这个源文件中,用关键字extern修饰file2中定义的变量。当然,extern修饰函数的道理也一样。

5.2 static关键字

  这里总结下static关键字的用法,在不同的上下文环境中,static关键字具有不同的意思。
  1. 当它用于函数定义、或者代码块以外的变量声明时,static关键字用于修改标识符的链接属性从external改为internal,但标识符的存储类型和作用域不受影响。用于这种方式声明的函数、变量只能在声明它们的源文件中使用。
  2.当它用于代码块内部的变量声明时,static关键字用于修改变量的存储类型,从自动变量改为静态变量,但变量的链接属性和作用域不受影响。用这种方式声明的变量在程序执行之前创建,并在程序的整个执行周期一直存在,而不是每次在代码块开始执行时创建,在代码块执行完毕后销毁。

你可能感兴趣的:(C语言,c语言)