文章插图
体系结构计划
外部链接的静态变量具有文件作用域、外部链接和静态存储期 。该类别有时称为外部存储类别(external storage class) , 属于该类别的变量称为外部变量(external variable) 。把变量的定义性声明(defining declaration)放在所有函数的外面便创建了外部变量 。当然 , 为了指出该函数使用了外部变量 , 可以在函数中用关键字extern再次声明 。如果一个源代码文件使用的外部变量定义在另一个源代码文件中 , 则必须用extern在该文件中声明该变量 。如下所示:
int Errupt;/* externally defined variable*/double Up[100];/* externally defined array*/extern char Coal;/* mandatory declaration if*//* Coal defined in another file*/void next(void);int main(void){extern int Errupt;/* optional declaration*/extern double Up[]; /* optional declaration*/...}void next(void){...}
注意 , 在main()中声明Up数组时(这是可选的声明)不用指明数组大小 , 因为第1次声明已经提供了数组大小信息 。main()中的两条extern声明完全可以省略 , 因为外部变量具有文件作用域 , 所以Errupt和Up从声明处到文件结尾都可见 。它们出现在那里 , 仅为了说明main()函数要使用这两个变量 。如果省略掉函数中的extern关键字 , 相当于创建了一个自动变量 。去掉下面声明中的extern:extern int Errupt;
便成为:int Errupt;
这使得编译器在main()中创建了一个名为Errupt的自动变量 。它是一个独立的局部变量 , 与原来的外部变量Errupt不同 。该局部变量仅main()中可见 , 但是外部变量Errupt对于该文件的其他函数(如next())也可见 。简而言之 , 在执行块中的语句时 , 块作用域中的变量将“隐藏”文件作用域中的同名变量 。如果不得已要使用与外部变量同名的局部变量 , 可以在局部变量的声明中使用auto存储类别说明符明确表达这种意图 。外部变量具有静态存储期 。因此 , 无论程序执行到main()、next()还是其他函数 , 数组Up及其值都一直存在 。下面3个示例演示了外部和自动变量的一些使用情况 。示例1中有一个外部变量Hocus 。该变量对main()和magic()均可见 。/* Example 1 */int Hocus;int magic();int main(void){extern int Hocus;// Hocus declared external...}int magic(){extern int Hocus;// same Hocus as above...}
示例2中有一个外部变量Hocus , 对两个函数均可见 。这次 , 在默认情况下对magic()可见 。/* Example 2 */int Hocus;int magic();int main(void){extern int Hocus;// Hocus declared external...}int magic(){// Hocus not declared but is known...}
在示例3中 , 创建了4个独立的变量 。main()中的Hocus变量默认是自动变量 , 属于main()私有 。magic()中的Hocus变量被显式声明为自动 , 只有magic()可用 。外部变量Hocus对main()和magic()均不可见 , 但是对该文件中未创建局部Hocus变量的其他函数可见 。最后 , Pocus是外部变量 , magic()可见 , 但是main()不可见 , 因为Pocus被声明在main()后面 。/* Example 3 */int Hocus;int magic();int main(void){int Hocus;// Hocus declared, is auto by default...}int Pocus;int magic(){auto int Hocus;// local Hocus declared automatic...}
这3个示例演示了外部变量的作用域是:从声明处到文件结尾 。除此之外 , 还说明了外部变量的生命期 。外部变量Hocus和Pocus在程序运行中一直存在 , 因为它们不受限于任何函数 , 不会在某个函数返回后就消失 。初始化外部变量外部变量和自动变量类似 , 也可以被显式初始化 。与自动变量不同的是 , 如果未初始化外部变量 , 它们会被自动初始化为0 。这一原则也适用于外部定义的数组元素 。与自动变量的情况不同 , 只能使用常量表达式初始化文件作用域变量:
int x = 10;// ok, 10 is constantint y = 3 + 20;// ok, a constant expressionsize_t z = sizeof(int);// ok, a constant expressionint x2 = 2 * x;// not ok, x is a variable
(只要不是变长数组 , sizeof表达式可被视为常量表达式 。)使用外部变量下面来看一个使用外部变量的示例 。假设有两个函数main()和critic() , 它们都要访问变量units 。可以把units声明在这两个函数的上面 , 如程序清单12.4所示(注意:该例的目的是演示外部变量的工作原理 , 并非它的典型用法) 。
推荐阅读
- 世界上使用最广泛的语言是什么?
- 我的 Linux 故事:用开源打破语言壁垒
- gcc编译器编译过程和链接过程
- C语言头文件路径剖析
- C语言的自定义输入和输出的三种方法
- C语言处理字符串的7个函数
- 编写C程序控制LED
- C语言的指针与多维数组
- C语言的数组的构建与打印
- Fyne - Go语言的跨平台UI工具包