本次为大家带来了变量的超细讲解,基本上将变量涉及的内容都讲到了,希望对大家有用,如果对你的帮助很大,建议一键三连(doge)
一、全局变量
1、定义:在函数外部定义的变量
2、作用域(在什么范围内有效):可以在本文件中其他函数所共用,它的有效范围是从定义变量的位置开始到本源文件结束
二、局部变量
1、定义:在函数内部定义的变量
在函数的开头定义(在在本函数范围内有效)
在函数内部的复合语句内定义(只在函数复合语句内部有效)
形式参数
2、作用域:(主函数或自定义函数)函数内部、复合语句(程序块)内有效
总结:局部变量只在自己的作用域内有效,离开作用域后该变量就无效,系统会把它占用的内存单元释放
三、全局变量和局部变量的命名规则
为了便于区别全局变量和局部变量,将全局变量名的第一个字母大写,局部变量用小写字母表示
四、非必要不使用全局变量
全局变量在程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟存储单元
降低了函数的通用性(c程序设计(谭浩强)200页)
使用过多的全局变量,会降低程序的清晰性(难以判断每个瞬间各个外部变量的值)
五、全局变量和局部变量同名
全局变量和局部变量同名时,遵循局部优先的规则,即:在局部变量的作用范围内,局部变量有效,全局变量被屏蔽,全局变量的值被局部变量覆盖
#include<stdio.h>
int a = 10;
int main()
{
int a = 5;
printf("%d", a);
return 0;
}
结果:
六、变量的存储方式和生命周期
以上是根据变量的作用域(即空间)的角度来观察,变量可以分为全局变量和局部变量
下面我们从变量值存在的时间(即生命周期)来讨论
1、存储方式
1、静态存储方式
静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式
2、动态存储方式
动态存储方式是在程序运行期间根据需要进行动态的分配存储空间的方式
2、用户存储空间
内存中供用户使用的存储空间有:
1、程序区(存放程序语句)
2、静态存储区
静态存储区存放的数据:
静态变量(static修饰的变量)
全局变量
3、动态存储区
动态存储区存放的数据:
函数形式参数(在调用函数时给参数分配存储空间)(存放在栈上)
自动变量(没有被static修饰的局部变量)(存放在栈上)
函数调用时的的现场保护(现场保护讲解:http://t.csdn.cn/gzIYe)和返回地址(存放在栈上)
以上这些数据在函数调用开始时动态的分配存储空间,函数结束时释放这些空间(动态的分配和释放空间)
动态内存分配的空间(malloc,realloc开辟的空间)(存放在堆区上的,由程序员自己开辟)
详见:http://t.csdn.cn/NBZ9V(讲解了动态存储区,静态存储区,堆,栈的区别)
七、变量的属性
1、每一个变量都由两个属性:
数据类型
数据的存储类别(数据在内存中存储的方式,如静态存储和动态存储方式)
2、C的存储类别包括:
自动的(auto)
静态的(static)
寄存器的(register)
外部的(extern)
八、局部变量的存储类别
1、自动变量(auto变量)
函数中的局部变量,如果不专门声明为static(静态)的存储类别,都是动态的分配存储空间,都是自动变量(如函数的形参,函数内的局部变量,复合语句内的局部变量)
实际上,auto关键字可以省略,不写auto则隐含指定为“自动存储类别”
#include<stdio.h>
int main()
{
int a = 10;
auto int a = 10;//两种写法等价
return 0;
}
2、静态局部变量(static局部变量)
static修饰的局部变量:
生命周期延长:该变量不随函数结束而结束
虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的。因为它是局部变量,只在自身的作用域范围内起作用
初始化:只在第一次调用该函数时进行初始化初始化
对于静态局部变量,编译时自动赋初值0(对数值型变量)或空字符'\0'(对于字符变量)。而对于自动变量来说 它的值时一个不确定的值。
记忆性:后序调用时,该变量使用前一次函数调用完成之后保存的值
存储位置:不会存储在栈上,放在数据段(静态存储区内)
例题:输出1到5的阶乘
#include<stdio.h>
int main()
{
int fac(int);
int i = 0;
for (i = 1; i <= 5; i++)
printf("%d!=%d\n", i, fac(i));
return 0;
}
int fac(int n)
{
static int f = 1;
f = f * n;
return f;
}
结果:
3、寄存器变量(register)
一般情况下,变量(包括静态存储方式和动态存储方式)的值是存放在内存中的。当程序用到哪一个变量的值是,由控制器发出指令将内存中的该变量的值送到运算器,经过运算器进行计算,如果需要存数,再从计算器将数据送到内存存放
如果有一些变量频繁使用,(例如,再一个函数内部执行10000词循环,每次循环中都要引用局部变量),则存取变量的值要花费不少时间。为提高执行效率,允许将局部变量的值放到CPU的寄存器中,需要用时直接从寄存器取出参加运算,不必再到内存中去存取。由于寄存器的存取速度远高于内存的存取速度,因此这样做可以提高执行效率。这种变量就叫做寄存器变量,用关键字register作声明
#include<stdio.h>
int main()
{
register int a =10;
printf("%d",a);
return 0;
}
九、全局变量的存储类别
全局变量都是存放再静态存储区的,因此它的生命周期都是固定的,存在于程序的整个运行过程。但是,对于局部变量的作用域我们需要进行细分(其作用可能是包括真个文件范围,也可能是文件中的一部分,是再一个文件有效,还是在一个程序的所有文件都有效)
1、在一个文件内扩展全局变量的作用域(extern关键字)
如果外部变量不在文件的开头定义,其有效作用范围只限于定义处到文件结束,在定义点之前的函数不能使用该全局变量。如果在定义点之前的函数要使用该全局变量,要用extern关键字对该外部变量声明,表示把该变量的作用域扩展到此处,有了此声明,就可以从“声明”处起,合法的使用该外部变量
例子:调用函数,求3个整数的最大值
#include<stdio.h>
int main()
{
extern int a, b, c;//extern a,b,c; //两种写法等价,类型可以省略不写
int max();//声明函数 //用extern声明后,a,b,c的作用域由声明处到文件结束
printf("请输入三个数字:");
scanf("%d%d%d", &A, &B, &C);
printf("the max is:%d", max());
return 0;
}
int A, B, C;//全局变量用大写,与局部变量进行区分
int max()
{
int m = 0;
m = a >b?a:b;
if (c > m)
return c;
else
return m;
}
2、将全局变量的作用域扩展到其他文件中
一个C程序可以由一个或多个源程序文件组成,如果一个由一个源文件组成,上述已经提到,如果是由多个源文件组成,那么在一个源文件中引用其他文件已经定义的全局变量应该怎么做?
例子:给定b的值,输入A和m,求a*b 和 a的m次方的值
//file1.c文件
#include<stdio.h>
int A;
int main()
{
int power(int);//声明函数
int b = 3, c, d, m;
printf("输入A的值和幂的值:");
scanf("%d%d", &A, &m);//13 3
c = A * b;
printf("%d *%d= %d\n", A, b, c);
d = power(m);
printf("%d ** %d = %d", A, m, d);
return 0;
}
//file2.c文件
extern A;
int power(int n)
{
int i = 1;
int y = 1;
for (i = 1; i <= n; i++)
{
y *= A;
}
return y;
}
结果:
3、将全局变量的作用域限制在本文件中
在程序设计时,有时希望本文件中的全局变量只限于本文件使用,其他文件不能使用,这时只要在定义全局变量时加一个static声明即可
//file1.c文件
#include<stdio.h>
static int A;
int main()
{
int power(int);//声明函数
int b = 3, c, d, m;
printf("输入A的值和幂的值:");
scanf("%d%d", &A, &m);//13 3
c = A * b;
printf("%d *%d= %d\n", A, b, c);
d = power(m);
printf("%d ** %d = %d", A, m, d);
return 0;
}
//file2.c文件
extern A;
int power(int n)
{
int i = 1;
int y = 1;
for (i = 1; i <= n; i++)
{
y *= A;
}
return y;
}
结果:报错
十、声明局部变量的存储类别和声明全局变量的存储类别的含义是不同的
1、对于局部变量来说,声明存储类别的作用是指定变量的存储区域(静态区还是动态区),以及由此产生的生命周期的问题
2、对于全局变量来说,声明存储类别是变量作用域扩展的问题,而全局变量本身就存放在静态区,不需要用存储类别来进行说明
十一、static声明变量的作用:
1、对局部变量用static声明:
把它分配在静态区域内,该变量在整个程序执行期间不释放,其所分配的空间始终存在(相当于延长了声明周期,但作用域不变)
2、对全集变用static声明:
该变量的作用域只限于本文件模块中
十二、存储类别的使用:
用存储类别关键字对变量进行声明时,时在定义变量的基础上加上这些关键字,而不能单股使用
以下用法时不对的
int a =10;
static a;
这样声明时错的,因为编译时被认为时“重新定义”