前言的闲话以及第一章的入门(八)

1.10 External Variables and Scope

The variables in main, such as line, longest, etc., are private or local to main. Because they are declared within main, no other function can have direct access to them. The same is true of the variables in other functions; for example, the variable i in getline is unrelated to the in copy. Each local variable in a function comes into existence only when the function is called, and disappears when the function is exited. This is why such variables are usually known as automatic variables, following terminology in other languages. We will use the term automatic henceforth to refer to these local variables.

main函数中的变量(如linelongest等)是main函数的私自变量或局部变量。由于它们是在main函数中声明的,因此其它函数不能直接访问它们。其它函数中声明的变量也同样如此。例如,getline函数中声明的变量icopy函数中声明的变量i没有关系。函数中的每个局部变量只在函数被调用时存在,在函数执行完毕退出时消失。这也是其它语言通常把这类变量称为自动变量的原因。以后我们使用“自动变量”代表“局部变量”

Because automatic variables come and go with function invocation, they do not retain their values from one call to the next, and must be explicitly set upon each entry. If they are not set, they will contain garbage.

由于自动变量只在函数调用执行期间存在,因此,在函数的两次调用之间,自动变量不保留前次调用时的赋值,且在每次进入函数时都要显式为其赋值。如果自动变量没有赋值,则其中存放的是无效值。

 

As an alternative to automatic variables, it is possible to define variables that are external to all functions, that is, variables that can be accessed by name by any function. (This mechanism is rather like Fortran COMMON or Pascal variables declared in the outermost block.) Because external variables are globally accessible, they can be used instead of argument lists to communicate data between functions. Furthermore, because external variables remain in existence permanently, rather than appearing and disappearing as functions are called and exited, they retain their values even after the functions that set them have returned.

除自动变量外,还可以定义位于所有函数外部的变量,也就是说,在所有函数中都可以通过变量名访问这种类型的变量(这机制同Fortran语言中的COMMON 变量或Pascal语言中最外层程序块声明的变量非常类似)。由于外部变量可以在全局范围内访问,因此,函数间可以通过外部变量交换数据,而不必使用参数表。再者,外部变量在程序执行期间一直存在,而不是在函数调用时产生、在函数执行完毕时消失。即使在对外部变量赋值的函数返回后,这些变量仍将保持原来的值不变。


An external variable must be defined, exactly once, outside of any function; this sets aside storage for it. The variable must also be declared in each function that wants to access it; this states the type of the variable. The declaration may be an explicit extern statement or may be implicit from context. To make the discussion concrete, let us rewrite the longest-line program with line, longest, and max as external variables. This requires changing the calls, declarations, and bodies of all three functions.

外部变量必须定义在所有函数之外,且只能定义一次,定义后编译程序将为它分配存储单元。在每个需要访问外部变量的函数中,必须声明相应的外部变量,此时说明其类型。声明时可以用extern 语句显式声明,也可以通过上下文隐式声明。为了更详细地讨论外部变量,我们改写上述打印最长文本行的程序,把linelongest max 声明成外部变量。这需要修改这3个函数的调用、声明与函数体。


#include <stdio.h>

#define MAXLINE 1000 /* maximum input line size */

int max; /* maximum length seen so far */

char line[MAXLINE]; /* current input line */

char longest[MAXLINE]; /* longest line saved here */

int getline(void);

void copy(void);

/* print longest input line; specialized version */

main()

{

int len;

extern int max;

extern char longest[];

max = 0;

while ((len = getline()) > 0)

if (len > max) {

max = len;

copy();

      }

if (max > 0) /* there was a line */

printf("%s", longest);

      return 0;

/* getline: specialized version */

int getline(void)

{

int c, i;

extern char line[];

for (i = 0; i < MAXLINE - 1&& (c=getchar)) != EOF && c != '\n'; ++i)

line[i] = c;

if (c == '\n') {

line[i] = c;

++i;

      }

line[i] = '\0';

return i;

}

/* copy: specialized version */

void copy(void)

{

int i;

extern char line[], longest[];

i = 0;

while ((longest[i] = line[i]) != '\0')

++i;

}


The external variables in main, getline and copy are defined by the first lines of the example above, which state their type and cause storage to be allocated for them. Syntactically, external definitions are just like definitions of local variables, but since they occur outside of functions, the variables are external. Before a function can use an external variable, the name of the variable must be made known to the function; the declaration is the same as before except for the added keyword extern.

在该例子中,前几行定义了maingetline copy 函数使用的几个外部变量,声明了各外部变量的类型,这样编译程序将为它们分配存储单元。从语法角度看,外部变量的定义与局部变量的定义是相同的,但由于它们位于各函数的外部,因此这些变量是外部变量。函数在使用外部变量之前,必须要知道外部变量的名字。要达到该目的,一种方式是在函数中使用extern 类型的声明。这种类型的声明除了在前面加了一个关键字extern 外,其它方面与普通变量的声明相同。


In certain circumstances, the extern declaration can be omitted. If the definition of the external variable occurs in the source file before its use in a particular function, then there is no need for an extern declaration in the function. The extern declarations in main, getline and copy are thus redundant. In fact, common practice is to place definitions of all external variables at the beginning of the source file, and then omit all extern declarations.

某些情况下可以省略extern 声明。在源文件中,如果外部变量的定义出现在使用它的函数之前,那么在那个函数中就没有必要使用extern声明。因此,maingetlinecopy中的几个extern 声明都是多余的。在通常的做法中,所有外部变量的定义都放在源文件的开始处,这样就可以省略extern声明。


If the program is in several source files, and a variable is defined in file1 and used in file2 and file3, then extern declarations are needed in file2 and file3 to connect the occurrences of the variable. The usual practice is to collect extern declarations of variables and functions in a separate file, historically called a header, that is included by #include at the front of each source file. The suffix .h is conventional for header names. The functions of the standard library, for example, are declared in headers like <stdio.h>.

如果程序包含在多个源文件中,而某个变量在file1 文件中定义、在file2 file3文件中使用,那么在文件file2 file3 中就需要使用extern 声明来建立该变量与其定义之间的联系。人们通常把变量和函数的extern 声明放在一个单独的文件中(习惯上称之为头文件),并在每个源文件的开头使用#include 语句把所要用的头文件包含进来。后缀.h约定为头文件名的扩展名


Since the specialized versions of getline and copy have no arguments, logic would suggest that their prototypes at the beginning of the file should be getline() and copy(). But for compatibility with older C programs the standard takes an empty list as an old-style declaration, and turns off all argument list checking; the word void must be used for an explicitly empty list.

在上述特别版本中,由于getlinecopy函数都不带参数,因此从逻辑上讲,在源文件开始处它们的原型应该是getline()copy()。但为了与老版本的C 语言程序兼容,ANSI C语言把空参数表看成老版本C语言的声明方式,并且对参数表不再进行任何检查。在ANSI C中,如果要声明空参数表,则必须使用关键字void进行显式声明。


You should note that we are using the words definition and declaration carefully when we refer to external variables in this section.``Definition'' refers to the place where the variable is 

created or assigned storage; ``declaration'' refers to places where the nature of the variable is stated but no storage is allocated.

读者应该注意到,这节中我们在谈论外部变量时谨慎地使用了定义(define)与声明declaration)这两个词。“定义”表示创建变量或分配存储单元,而“声明”指的是说明变量的性质,但并不分配存储单元。


By the way, there is a tendency to make everything in sight an extern variable because it appears to simplify communications - argument lists are short and variables are always there when you want them. But external variables are always there even when you don't want them. Relying too heavily on external variables is fraught with peril since it leads to programs whose data connections are not all obvious - variables can be changed in unexpected and even inadvertent ways, and the program is hard to modify. The second version of the longest-line program is inferior to the first, partly for these reasons, and partly because it destroys the generality of two useful functions by writing into them the names of the variables they manipulate.

顺便提一下,现在越来越多的人把用到的所有东西都作为外部变量使用,因为似乎这样可以简化数据的通信——参数表变短了,且在需要时总可以访问这些变量。但是,即使在不使用外部变量的时候,它们也是存在的。过分依赖外部变量会导致一定的风险,因为它会使程序中的数据关系模糊不清——外部变量的值可能会被意外地或不经意地修改,而程序的修改又变得十分困难。我们前面编写的打印最长文本行的程序的第2 个版本就不如第1 个版本好,原因有两方面,其一便是使用了外部变量;另一方面,第2 个版本中的函数将它们所操纵的变量名直接写入了函数,从而使这两个有用的函数失去了通用性。

 

At this point we have covered what might be called the conventional core of C. With this handful of building blocks, it's possible to write useful programs of considerable size, and it would probably be a good idea if you paused long enough to do so. These exercises suggest programs of somewhat greater complexity than the ones earlier in this chapter.



















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值