学习C第一章入门篇10: 外部变量和作用域
在函数(function)中所声明的变量对于该函数是私有(private)的或者局部(local)的, 其它函数不能直接访问它们。 每一个在函数中的局部变量从该函数被调用起开始存在;当该函数结束退出(exit)的时候, 这些局部变量也随之消失。 这也是为什么这些变量在其它语言当中的术语叫做: 自动(automatic)变量。
除了自动变量外, 我们还有一个选择, 就是将变量定义为对于所有函数而言一个外部(external)的存在(在函数外部定义的外部变量)。 也就是说, 这样定义变量之后, 这些外部变量能通过调用变量名的方式来被其它任意函数访问。 同时, 与局部变量不同的是, 外部变量是永久存在的, 不像局部变量一样只存在于所在(局部变量被定义)函数被调用起至结束退出期间。
一个外部(external)变量必须在任意函数外部被定义(defined)一次(有且只有一次), 以求为其分配存储空间。 而每一个想访问这些外部变量的函数必须在其内部声明(declare)所需要访问的外部变量。(这也声明(state)了相应变量对应的变量类型)。 这个声明(declaration)可以是明确地用extern
来声明, 也可以是有时根据所处的环境不必用extern
来特别声明了。
在书中, 给出的例子缩略后如下:
#include <stdio.h>
#define MAXLINE 1000
int max;
char line[MAXLINE];
char longerst[MAXLINE];
int getline(void);
void copy(void);
main() {
......
extern int max;
extern char longest[];
......
}
int getline(void) {
......
extern char line[];
......
}
void copy(void) {
......
extern char line[], longest[];
......
}
从语法上而言, 外部变量的定义(definition)和本地变量的定义是一样的, 但是区别在于, 外部变量是出现在函数之外的, 即外部的。 在一个函数能使用外部变量之前, 对应外部变量名必须对于该函数而言是已知的。 上面所演示的通过extern
关键词来声明的用法便是一种能达到该目的的方式。
在一些特定的情况下, extern
声明可以省略。 如果一个外部变量是在调用它的函数之前被定义的, 那么在这种情况下便不必在调用函数里采用extern
来额外声明了。 因此, 很多情况下, 我们可将所有外部变量置于源文件开头, 这样便可省略所有的extern
声明了。
如果一个程序是由数个源文件 组成, 然后其中有个变量在 源文件1 中被定义, 在 源文件2 和 源文件3 中被使用, 那么此时, 有必要在*源文件2 和源文件3 中使用extern
声明。 在实际操作中, 我们常采用的方式是: 将变量和函数的extern
声明置于一个单独的文件中,由于历史的原因, 我们称该文件为header文件。 header文件的后缀是*.h**(约定俗成),header文件通常在每个源文件开头通过#include
来包含进去。
在上面的阐述中, 我们也许能发现两个术语出现的频率很高, 分别是: definition 以及 declaration. "Definition"引用的是变量的储存空间; 而"declaration"引用的是变量的类型(不分配储存空间)。
书后练习题1-20:
Write a program detab that replaces tabs in the input with the proper number of blanks to space to the next tab stop. Assume a fixed set of tab stops, says every n columns. Should n be a variable or a symbolic parameter?
我写的版本:
#include <stdio.h>
#define MAX 1000
int column_cap = 8;
int column_count = 0;
char line[MAX];
int getline_alt(char[], int);
int main() {
int count;
count = 0;
while ((count=getline_alt(line, MAX)) > 0) {
printf("%s", line);
}
printf("\n");
return 0;
}
int getline_alt(char line[], int limit) {
int result;
result = 0;
int c;
while ((c=getchar())!=EOF && c!='\n') {
if (c=='\t') {
int i;
for (i=0; i<column_cap-column_count; i++) {
line[result++] = ' ';
}
column_count = 0;
} else {
column_count = (column_count+1) % 8;
line[result++] = c;
}
}
if (c=='\n') {
line[result++] = c;
}
line[result] = '\0';
return result;
}
参考: 《The C Programming Language》- Chapter 1.10