在函数(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