C/C++培训
达内IT学院
400-996-5531
今天我们来讨论一个对初学者很重要也很基础的问题:以变量定义为讨论对象来说说各种定义或者声明在程序中出现的位置引起的语义问题。这里将涉及到很重要的两个概念:作用域和存在期。
1. 外部定义的变量与声明
外部变量也叫全局变量,它的生存期从定义开始直到程序运行结束,而作用域是从定义处到程序结束。它可以在main函数外的几乎任何地方定义,如:
#include <stdio.h>
int a = 15 , b = 20;
int main()
{
printf("a = %d , b = %d", a , b );
return 0;
}
亦或者:
#include <stdio.h>
int main()
{
printf("a = %d , b = %d", a , b );
return 0;
}
int a = 15 , b = 20;
注意,在第二种情况下,运行程序时a和b的值是打印不出来的,因为printf函数不在全局变量的作用域中,此时若想使用全局变量,则需要另外声明这个已经定义好的变量,代码如下:
#include <stdio.h>
int main()
{
extern int a = 15 , b = 20;
printf("a = %d , b = %d", a , b );
return 0;
}
int a = 15 , b = 20;
类似的情况:
用C语言编写程序的时候,我们经常会遇到这样一种情况:希望在头文件中定义一个全局变量,然后包含到两个不同的c文件中,希望这个全局变量能在两个文件中共用。
举例说明:项目文件夹project下有main.c、common.c和common.h三个文件,其中common.h文件分别#include在main.c和common.c文件中。现在希望声明一个字符型变量key,在main.c和common.c中公用。如下图所示:
有人想,既然是想两个文件都用,那就在common.h中声明一个unsigned char key,然后由于包含关系,在main.c和common.c中都是可见的,所以就能共用了。
这种想法其实是很多初学者都会想到的,想起来确实有道理,但是实际写出来,我们发现编译的时候编译器提示出错,一般提示大概都类似于:Error: L6200E: Symbol key multiply defined (by common.o and main.o). 也就是说编译器认为我们重复定义了key这个变量。这是因为#include命令就是原封不同的把头文件中的内容搬到#include的位置,所以相当于main.c和common.c中都执行了一次unsigned char key,而c语言中全局变量是项目内(或者叫工程内)可见的,这样就造成了一个项目中两个变量key,编译器就认为是重复定义。
正确的解决办法:使用extern关键字来声明变量为外部变量。具体说就是在其中一个c文件中定义一个全局变量key,然后在另一个要使用key这个变量的c文件中使用extern关键字声明一次,说明这个变量为外部变量,是在其他的c文件中定义的全局变量。请注意我这里的用词:定义和声明。例如在main.c文件中定义变量key,在common.c文件中声明key变量为外部变量,这样这两个文件中就能共享这个变量key了,如下图所示。
代码如下(只写跟我们所说问题有关的部分):
(1)main.c文件
#include "common.h"
unsigned char key;
(2)common.c文件:
#include "common.h"
extern unsigned char key;
2. 外部变量和自动变量
作为刚入门的初学者,知道了main函数的地位可能会认为在main函数里定义的变量可以在其他函数中使用。但要注意的是main函数也只是一个普通数,从作用域的角度来看,其内部定义也是局部的不能在main函数体外部使用。全局变量的存在期是整个程序的执行期间,而自动变量也就是局部变量只能存在于管它的那个复合语句下面,举代码为例:
for (n = 0; n < 10; n++)
{
int m ;
if (n == 0) m = 2;
/* 循环到第二次执行到这里时m的值无法确定 */
}
第一次循环时n=0,m=2,但它的寿命1到这里也就结束了,下一次循环,你看到的m已经是新的它了。
3. 外部静态变量
全局变量虽然生存期长,但一个缺陷就是作用域太广,当程序非常大需要由几个人或者几个小组共同开发时,全局的名字很容易冲突,为了解决这一问题C语言提供了静态外部变量的概念,作用域局限于一个源程序文件,这一变量也是外部变量,定义时加上关键字 static
4. 静态局部变量
举一个实际问题为例:
for (n = 1; n*n <=200 ; n++)
{
printf(“%d”, n*n);
format( );
}
int m = 0;
void format (void)
{
if(++m == 10 )
{
putchar('\n');
m = 0;
}
else putchar(' ');
}
这一函数虽然能正常工作。但按照设想 m 保存的应该是format的私用数据,但若m作为一个局部变量,程序无法正常运行,如果不知道为什么可以去文章前面看,因此它不得不是一个外部变量,但这样的话如果你在其他函数里不小心用了m就很尴尬了,你在其他函数里改了它的值,forma就会发生计算错误。
这个问题就引出了我们要讨论的一种对变量的需求:局部作用域,全程存在期,一次初始化。
而恰好,C的局部静态变量就是这样一个变量,以下是用静态局部变量修改的代码:
void format (void)
{
static int m = 0;
if(++m == 10 )
{
putchar('\n');
m = 0;
}
else putchar(' ');
}
注意将局部静态变量与外部静态变量区分。
局部静态变量能在函数的不同调用间保持不变。
5. 默认初始化
外部变量和局部静态变量定义时未初始化,系统自动将其值初始化为0,但自动变量定义时系统不会自动初始化,这是初学者经常会犯的一个问题。
填写下面表单即可预约申请免费试听!怕钱不够?可就业挣钱后再付学费! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!
Copyright © 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有
Tedu.cn All Rights Reserved