从头学C(35)作用域规则

0

在上一节从头学C(34)外部变量中,我们留了一个未说明的问题,就是为什么说 pop_push.c 中的栈相关信息对 main 函数来说是隐藏的。

第四章 函数与程序结构 >> 4.4 作用域规则

1. 名字的作用域

名字的作用域是指程序中可以使用该名字的部分。

对于在函数开头位置声明的自动变量(局部变量)来说,它的作用域是声明该变量名的函数。所以,不同函数内声明的同名变量之间是没有任何关系的。包括函数的参数,也可以把它看做是局部变量。

对于外部变量或函数,它们的作用域是从声明它的地方开始,到其所在的(待编译的)源文件的末尾结束。

如果在同一个源文件中,按如下顺序依次定义:

main() {......}

int sp = 0;
double val[MAXVAL];

void push(double f) {......}
double pop() {......}

那么 push 和 pop 函数可以直接访问变量 sp 和 val[ ] ,但是 main 既不可以访问这两个变量,也不能访问 push 和 pop。

而在上一节中,因为变量 sp 和 val[ ] 都是在 pop_push.c 中定义的外部变量(它们的作用域也仅限于 pop_push.c ),main.c 没有声明这两个变量,因此 main 函数不能访问这两个变量。

当然,可以通过在 main.c 中使用关键字 extern 来声明这两个变量,则 main 函数便可访问这两个变量了。(虽然我们可以这么做,但如前所说,栈的细节我们在 main 函数中并不关注)

2. 外部变量的声明和定义

声明和定义的概念一定要区分开:

  • 变量声明用于说明变量的属性(主要是变量类型);
  • 变量定义除了说明变量的属性,还将引起存储器的空间分配。

如果将下列语句放在所有函数外部:

int sp;
double val[MAXVAL];

那么这两条语句将定义外部变量 sp 和 val,并为它们分配存储单元,同时作为该源文件中其余部分的变量声明。

而下面这两条语句:

extern int sp;
extern double val[];

则为源文件的其余部分声明了一个 int 型变量及一个 double 数组类型的外部变量 val(数组长度在其他地方定义),但这两条语句也仅仅也只是声明而已,并没有为它们建立变量或分配存储空间。

另外还需要注意的地方是:

  1. 在一个程序的所有源文件中,一个外部变量只能在某个文件中被定义一次,其他文件可以通过 extern 声明访问它们;
  2. 外部变量的定义中必须指定数据长度,但 extern 声明可以不用指定具体长度;
  3. 外部变量的初始化只能出现在其定义中;

Leave A Reply