局部变量与全局变量

数据的存储类型
一、变量的作用域
变量的作用域是指变量有效性的范围,与变量定义的位置密切相关,作用域是从空间这个角度来描述变量的,按照作用域的不同,变量可分为局部变量和全局变量。
1、局部变量
在函数(或代码块)内部定义的变量,也称为内部变量,局部变量只能在定义它的函数(或代码块)内使用,其他函数均不能使用,局部变量的作用域,限于说明它的代码块内:从说明的地方开始至所在的代码块结束。注意,在同一个作用域内,不允许有同名的变量。
例如:在同一个main()函数中,定义了三个数据类型和变量名均相同的局部变量i。在访问这些变量i中,他们不会混淆,它们是三个不同的局部变量。它们各有自己的作用域。
代码如下:
#include <stdio.h>
void main()
{
int i=10;
printf("The first i is %d\n",i);
printf("Enter a positive or negative number:  ");
scanf("%d",&i);
    
printf("In main() i=%d\n",i);
if(i>0)
{
int i=-10;
printf("In if i is %d\n",i);
}
else
{
int i=20;
printf("In else i is %d\n",i);
}
printf("The i in main() still is %d\n",i);
return;
}
运行结果:
 
2、全部变量
作用域是从定义点开始直到程序文件结束的变量,称为全局变量。全局变量在程序的整个运行过程中,都占用存储单元。在一个函数中改变了全局变量的值,其他函数可以共享。全局变量相当于起到在函数间传递数据的作用。
例如:求一元二次方程的根:ax2 + bx + c =0
代码如下:
#include <stdio.h>
#include <math.h>
float X1,X2,p,q,d;      //定义全局变量


void greater_than_zero(float,float);  //函数声明
void equal_to_zero(float,float);
void smaller_than_zero(float,float);


void main()
{
float a,b,c;          //定义局部变量
printf("Enter a,b,c:  ");
scanf("%f%f%f",&a,&b,&c);


d=b*b-4*a*c;
if(d>0)
{
greater_than_zero(a,b);
printf("X1 = %5.2f\tX2 = %5.2f\n",X1,X2);
}
else if(d==0)
{
equal_to_zero(a,b);
printf("X1 = X2 = %5.2f\n",X1);
}
else
{
smaller_than_zero(a,b);
printf("X1 = %5.2f+%5.2fi\n",p,q);
printf("X2 = %5.2f-%5.2fi\n",p,q);
}
return;


}


void greater_than_zero(float x,float y)
{
X1=(-y+sqrt(d))/(2*x);
X1=(-y-sqrt(d))/(2*x);
return;
}


void equal_to_zero(float x,float y)
{
X1=(-y)/(2*x);
return;
}


void smaller_than_zero(float x,float y)
{
p=-y/(2*x);
q=sqrt(-d)/(2*x);
return;
}
二、变量的存储类型
运行程序时,系统在内存中为数据的存储开辟了两块区域:静态数据区和动态数据区,分配在静态数据区的变量称为静态变量,分配在动态数据区的变量称为动态变量。在静态和动态两大类的存储方法中,C语言将变量的存储类型分为四种,其存储类型说明符和名称如下:
类型说明符          名称
auto                自动变量
static               静态局部变量
extern              外部变量
register             寄存器变量
在变量定义语句中,存储类型符放在它所修饰的数据类型前面,一般形式为:
存储类型符    数据类型符    变量名表;
1、自动变量auto(动态存储类型)
在函数内定义的或在函数的语句块内定义的变量,若存储类型省略或写为auto,都是自动变量。此前的程序中使用的都属于自动变量。下面的两条变量的定义语句是等价的:
int  a,b;   等价于:
auto int a,b;
注意:自动变量在初始化前,或没有赋值前,它的值是不确定的。
2、静态局部变量static(静态存储类型)
静态局部变量在静态存储区为其分配存储空间,在整个程序运行期间都不释放,变量的生存期是程序运行期。虽然静态局部变量的存储空间在整个程序运行中都保持着,但是,在它的作用域以外,仍然是不能被引用的。
例如:函数numbers()是一个数发生器,每调用函数numbers()一次,产生一个整数。每个数的产生都是在上次产生的数的基础上计算出来的。
代码如下:
#include <stdio.h>
int numbers(void);
main()
{
int i;
for(i=0;i<10;i++)
printf("%d  ",numbers());
return 0;
}


int numbers(void)
{
static int num1=0,num2=0;  //定义静态变量num1,num2
num1 = num1 + 4;
num2 = num2 + 7;
return num2 % num1;
}
运行结果:
 


3、寄存器变量register()
如果变量在程序运行中使用非常频繁,则为存取该变量要消耗很多时间。利用寄存器操作速度快的特点,将变量存放在CPU的寄存器中,可以提高程序的运行效率。寄存器变量占用CPU的高速寄存器,不占用内存单元。变量的值就保存在CPU的寄存器中。
寄存器变量仅能用于定义局部变量或是函数的形参,不能用于全局变量。在ANSI中,寄存器变量可以用于任何数据类型,但Turbo C++将寄存器变量只限用于char型和int型变量。
例如:
register  int  num;
register型变量常用于作为循环控制变量,这是使用它的高速特点的最佳场合。比较下面两个程序的运算速度。
main ( )
{
register int temp, i;
for ( i=0; i<=30000; i++ )
for ( temp=0; temp<=100; temp++ ) ;
printf ("ok\n");
}




#include <stdio.h>
main( )
{
int temp, i;
for ( i=0; i<=30000; i++ )
for ( temp=0; temp<=100; temp++ ) ;
printf ("ok\n");
}


三、全局变量的存储定义
1、外部全局变量
全局变量是在函数外部定义的变量。变量在编译时分配在静态数据区,生存期是程序的运行期间。作用域是从定义点往后的所有定义的函数均有效。但当函数内的局部变量同名时,局部变量是有效的,全局变量无效。
如果在一个源文件中将某些变量定义为全局变量,而这些全局变量允许其他源文件中的函数引用的话,就需要有一种方法,把程序的全局变量告诉相关的模块文件。解决的办法是,在一个模块文件中将变量定义为全局变量,而在引用这个变量的模块文件中,用存储类型符extern将其说明为外部变量。即extern定义符的作用只是将一个文件定义全局变量的作用域延伸到本源程序文件。
例如:文件file1定义主函数和一个全局变量m。文件file2定义计算阶乘的函数fact(),并说明变量m为外部的。
//file1.c
#include <stdio.h>
int fact(void);
int m;
void main()
{
printf("Enter a number:  ");
scanf("%d",&m);


printf("%d!=%d\n",m,fact());
return;
}


//file2.c
extern int m;
int fact(void)
{
int result=1,i;
for(i=1;i<=m;i++)
result=result+i;
return(result);
}
2、静态全局变量
静态全局变量是在被定义的源程序文件以外是不可见的。也就是说,静态全局变量只限于它所在的源程序文件中的函数引用,而不能被其他的源程序文件中的函数引用。其定义形式和局部静态变量是一样的,其一般形式为:
static 数据类型  变量;
注意:
(1)静态全局变量和静态局部变量分配在静态数据区,生存期是程序运行期。但静态全局变量与静态局部变量的作用域方面是不相同的;
(2)静态全局变量和全部变量在同一文件内的作用域是一样的,但全局变量的作用域可延伸到其他程序文件;
(3)静态局部变量与(动态)局部变量在作用域上相同的,但前者分配在静态数据区,后者分配在动态数据区,因而,他们的生存期是不同的。
//第一个文件file1.c
static int num1,num2;
int numbers(void)
{
num1 = num1 + 4;
num2 = num2 + 7;
return num2%num1;
}
void num_init(int x1,int x2)
{
num1 = x1;
num2 = x2;
}




//file2.c
#include <stdio.h>
#include "file1.c"
int numbers(void);
void num_init(int,int);


main(void)
{
int i;
num_init(5,6);
for(i=0;i<10;i++)
printf("%d  ",numbers());
return 0;
}


总结:
(1)一个数据包含有两方面的属性:数据类型和存储类型;
(2)从作用域的角度,有局部变量和全局变量,按存储类型分,局部变量又分为自动的、静态的、寄存器三种;全局变量又分为静态的和外部的两种;
(3)从生存期的角度,有动态存储和静态存储两类,动态存储类的数据分配在动态数据区,是在进入相应的定义块时分配存储单元,如自动变量、寄存器变量和形参;静态存储类的数据分配在静态数据区,是编译时分配的,在整个程序运行期间都存在,如静态局部变量、静态外部变量和全局变量。


四、内部函数和外部函数
对于一个多源程序文件的C程序来说,根据一个函数能否调用其他源程序文件的函数,将函数分为内部函数和外部函数。
1、内部函数
函数只能被源程序文件的函数所调用,这样的函数称为内部函数,内部函数也叫做静态函数,内部函数在定义时,要在函数类型前加上说明符static,例如:
static char myfunction(char ch)
{
}
如果在定义函数时省略extern,则隐含为外部函数。例如:
void num_init(){}
int numbers(){}
在定义时虽然没有用extern说明,但实际上就是外部函数,它们可以被另一个文件的函数调用。在需要调用外部函数的文件中,用extern说明所用的函数是外部函数。例如:
extern int sum();


#include <stdio.h>
#include "file4.c"
int sum();
int i,j;
main()
{
int x;
printf("Enter two numbers: ");
scanf("%d%d",&i,&j);
x=sum();
printf("  sum=%d\n",x);
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值