1、局部变量是否能和全局变量重名?
答:能,局部会屏蔽全局。要用全局变量,须要使用"::"
局部变量能够与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内能够定义多个同名的局部变量,比方在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内。
2、怎样引用一个已经定义过的全局变量?
答:extern
能够用引用头文件的方式,也能够用externkeyword,假设用引用头文件方式来引用某个在头文件里声明的全局变理,假定你将那个变写错了,那么在编译期间会报错,假设你用extern方式引用时,假定你犯了相同的错误,那么在编译期间不会报错,而在连接期间报错。
3、全局变量可不能够定义在可被多个.C文件包括的头文件里?为什么?
答:能够,在不同的C文件里以static形式来声明同名全局变量。
能够在不同的C文件里声明同名的全局变量,前提是当中仅仅能有一个C文件里对此变量赋初值,此时连接不会出错
4、static全局变量与普通的全局变量有什么差别?static局部变量和普通局部变量有什么差别?static函数与普通函数有什么差别?
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。
这两者在存储方式上并无不同。这两者的差别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件里都是有效的。而静态全局变量则限制了其作用域,
即仅仅在定义该变量的源文件内有效,
在同一源程序的其他源文件里不能使用它。因为静态全局变量的作用域局限于一个源文件内,仅仅能为该源文件内的函数公用,因此能够避免在其他源文件里引起错误。
从以上分析能够看出,
把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。
static函数与普通函数作用域不同,仅在本文件。仅仅在当前源文件里使用的函数应该说明为内部函数(static),内部函数应该在当前源文件里说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件里说明,要使用这些函数的源文件要包括这个头文件
static全局变量与普通的全局变量有什么差别:static全局变量仅仅初使化一次,防止在其它文件单元中被引用;
static局部变量和普通局部变量有什么差别:static局部变量仅仅被初始化一次,下一次根据上一次结果值;
static函数与普通函数有什么差别:static函数在内存中仅仅有一份,普通函数在每一个被调用中维持一份拷贝.
5、程序的局部变量存在于(堆栈)中,全局变量存在于(静态区
)中,动态申请数据存在于( 堆)中。
变量能够在程序中三个地方说明: 函数内部、函数的參数定义中或全部的函数外部。依据所定义位置的不同, 变量可分为局部变量、形式參数和全程变量。从空间角度来看,变量能够分为全局变量和局部变量,而从时间角度来分的 能够有静态存储变量和动态存储变量之分。
一。全局变量和局部变量
1。局部变量
他是 指在函数内部定义的变量 作用域为定义局部变量的函数 也就是说他仅仅能在定义他的函数中使用
最值得注意的是 仅仅有在程序运行到定义他的模块时才干生成,一旦运行退出该模块则起变量消失
eg.
func ()
{
int x; 局部变量x的作用域 非常明白
......
}
2。全局变量
在程序运行的过程中一直有效
eg.
int x=1;
func ()
{
x=x+1;
}
func1 ()
{
x=x-1;
}
main ()
{
}
由此不难看出整型x的作用范围
对于全局变量 假设在定义的时候不做初始化 则系统将自己主动为起赋值 数值型为0
字符型为空‘/0‘
全局变量的弊端 添加内存开销 减少函数的通用性
定义全局变量时 理想的位置是在文件的开头 当这些函数以及同一个程序中的其它源程序文件里的某些函数须要使用该全局变量时 在函数内部对该变量使用extern 加以说明 说明他是外部的
(这里还要做具体的解说)
eg.
main ()
{
extern int a,b;
printf ("mIn is %d/n",min(a,b));
}
int a=1,b=2;
int min (x,y)
int x,y;
{
int z;
z=x<y?x:y;
return(z);
}
我还要说明的是 对外部变量的说明和对全局变量的定义不是一回事
对外部变量的说明 仅仅是声明该变量是在外部定义过的一个全局变量 在这里引用 而对全局变量的定义则是要对起分配存储单元的
一个全局变量仅仅能定义一次 但是却能够多次引用
*** 在同一源文件里,全局变量和局部变量同名时,在局部变量的作用域内,全局变量不起作用的。
二。静态存储变量和动态存储变量
对于程序执行期间依据须要进行暂时动态分配存储空间的变量 为动态存储变量
对于那些程序执行期间永久占用固定内存的变量 称为静态存储变量
还要说明的是 程序的指令代码是存放在程序代码区的 静态存储变量是存放在静态数据区的 包含全局变量等 而程序中的动态存储变量存放在动态数据区 如函数的形參以及函数调用时的返回地址等
三。C语言中的变量存储分类指定
auto
auto称为自己主动变量 假设函数不做其它说明的话 均为自己主动变量
static
static称为静态变量。依据变量的类型能够分为静态局部变量和静态全程变量。
1. 静态局部变量
它与局部变量的差别在于: 在函数退出时, 这个变量始终存在, 但不能被其他函数使用, 当再次进入该函数时, 将保存上次的结果。其他与局部变量一样。
2. 静态全程变量
Turbo C2.0同意将大型程序分成若干独立模块文件分别编译, 然后将全部模块的目标文件连接在一起, 从而提高编译速度, 同一时候也便于软件的管理和维护。静态全程变量就是指仅仅在定义它的源文件里可见而在其他源文件里不可见的变量。它与全程变量的差别是: 全程变量能够再说明为外部变量(extern), 被其他源文件使用, 而静态全程变量却不能再被说明为外部的, 即仅仅能被所在的源文件使用。
extern
extern称为外部变量。为了使变量除了在定义它的源文件里能够使用外, 还要被其他文件使用。因此, 必须将全程变量通知每个程序模块文件, 此时可用extern来说明。
eg.
文件1为file1.c 文件2为file2.c
int i, j;/*定义全程变量*/ extern int i, j;/*说明将i, j从
文件1中复制过来*/
char c; extern char c; /*将c复制过来*/
void func1(int k); func2() /*用户定义函数*/
{
main() static float k;/*定义静态变量*/
{ i=j*5/100;
func1(20);/*调用函数*/ k=i/1.5;
func2(); .
. .
. .
. }
}
func1(int k) /*用户定义函数*/
{
j=k*100;
}
对于以上两个文件file1.c和file2.c, 用Turbo C2.0的集成开发环境进行编译
连接时, 首先应建立一个.prj的文件。比如file.prj, 该文件内容例如以下:
file1.c
file2.c
然后将file.prj的文件名称写入主菜单Project中的Project Name项中。 再用F9
编译连接, 就可产生一个文件名称为fioe.exe的可运行文件。
register
register称为寄存器变量。它仅仅能用于整型和字符型变量。定义符register说明的变量被Turbo C2.0存储在CPU的寄存器中, 而不是象普通的变量那样存储在内存中, 这样能够提高运算速度。可是Turbo C2.0仅仅同意同一时候定义两个寄存器变量,一旦超过两个, 编译程序会自己主动地将超过限制数目的寄存器变量当作非寄存器变量来处理。因此, 寄存器变量经常使用在同一变量名频繁出现的地方。
另外, 寄存器变量仅仅适用于局部变量和函数的形式參数, 它属于auto型变量,
因此, 不能用作全程变量。定义一个整型寄存器变量可写成:
register int a;
对于以上所介绍的变量类型和变量存储类型将会在以后的学习中, 通过例行程序中的定义、使用来逐渐加深理解。
1.程序的内存区域
并非全部的变量时时刻刻都是可知的。一些变量在整个程序中都是可见的,它们称为全局变量。一些变量仅仅能在一个函数中可知,称为局部变量。要了解变量的这些属性,应先弄清程序在内存中的分布区域,见图5-2。
图5-2 程序在内存中的区域
一个程序将操作系统分配给其执行的内存块分为4个区域:
(1)代码区,存放程序的代码,即程序中的各个函数代码块。
(2)全局数据区,存放程序的全局数据和静态数据。
(3)堆区,存放程序的动态数据。
(4)栈区,存放程序的局部数据,即各个函数中的数据。
2.全局变量
在函数外边訪问的变量被觉得是全局变量,并在程序的每一个函数中是可见的。全局变量存放在内存的全局数据区。全局变量由编译器建立,而且初始化为0,在定义全局变量时,进行专门初始化的除外。
比如,以下的代码定义并使用了全局变量。:
int
n=5; //全局变量
void main()
{
int
m=n;
//...
}
void func()
{
int
s;
n=s;
//...
}
n在不论什么函数的外部定义。 n被初始化为5,
假设n不在定义时初始化,则C++将其初始化为0。
main()函数使用变量n1,函数func()改动变量n。两个函数都訪问了同一个内存区域。这样定义的全局变量。在全部函数中都可见。假设一个函数改动了n,则全部其它的函数都会看到改动后的变量。
全局变量在主函数main()执行之前就開始存在了。所以主函数中能够訪问n变量。
全局变量通常在程序顶部定义。全局变量一旦定义后就在程序的不论什么地方可知。能够在程序中间的不论什么地方定义全局变量,但要在不论什么函数之外。全局变量定义之前的全部函数定义,不会知道该变量。比如:
void
main()
{
int m=n; //error:n无定义
//...
}
int
n;//全局变量
void func()
{
int
s=3;
n=s;
//...
}
该代码中的全局变量n不能被主函数main()訪问。
编译该代码,将会引起main()中的m初始化语句报告一个“n无定义”的错误。
3.局部变量
在函数内部定义的变量仅在该函数内是可见的。另外,局部变量的类型修饰是auto,表示该变量在栈中分配空间,但习惯上都省略auto。比如:
void
main()
{
int n; //等价于auto
intn;
//...
}
void func()
{
int
n;
//...
}
代码中两个函数都包括一个变量定义语句。在函数内定义的变量局部于该函数。main()函数中有一个变量n,func()函数中也有一个变量n,但它们是两个不同位置的变量。
一个函数能够为局部变量定义不论什么名字,而不用操心其它函数使用过相同的名字。
这个特点和局部变量的存在性使C++适合于由多个程序猿共同參与的编程项目。项目管理员为程序猿指定编写函数的任务,并为程序提供參数和期望的返回值。然后,程序猿着手编写函数,而不用了解程序的其它部分和项目中其它程序猿所使用的变量名。
函数中的局部变量存放在栈区。在函数開始执行时,局部变量在栈区被分配空间,函数退出时,局部变量随之消失。
局部变量没有初始化。假设局部变量不被显式初始化,那么,其内容是不可预料的。比如:
//*********************
//**
ch5_1.cpp **
//*********************
#include <iostream.h>
int func1();
int func2();
void main()
{
func1();
cout
<<func2() <<endl;
}
int func1()
{
int n=12345;
return
n;
}
int func2()
{
int m;
return m;
//warning:possible use of ‘m‘ before definition
}
执行结果为:
12345
主函数main()先后调用了函数func1()和func2(),它们都是无參并返回整数的函数。
在func1()中,定义了局部变量n,并给其初始化为12345。在func2()中,定义了局部变量m,没有初始化。
但是在将该变量值返回后,在主函数中输出该值,却发现为12345,
恰好就是funcl()函数中初始化的值。这说明,func2()中,没有显式初始化的局部变量m,C++也未给其默认初始化,其值保留为原内存位置的值。那么,原内存位置为什么恰巧是存放值12345的位置呢?请见下节“函数调用机制”。
要点:
1、全局变量:
(1)在函数外定义
(2)在全局可见
(3)一般在程序顶部定义
(4)存放在内存的全局数据区
(5)如在定义时未初始化,则其值为0
(6)假设一个函数改动了n,则全部其它的函数都会看到改动后的变量
2、局部变量:
(1)在函数内部定义
(2)仅在该函数内可见
(3)存放于栈区,函数退出时,局部变量随之消失
(4)不同函数可使用同一个变量名
(5)假设局部变量不被显式初始化,其内容则不可预料
局部变量
局部变量也称为内部变量。局部变量是在函数内作定义说明的。其作用域仅限于函数内部,离开该函数后再使用这样的变量是非法的。
局部变量从存储方式上可分为动态(auto)存储类型和静态(static)存储类型。
动态存储类型的局部变量都是动态的分配存储空间,数据存储在动态存储区(栈)中。函数调用结束后自己主动释放,生存期是在声明该变量的函数运行过程。
静态存储类型的局部变量则是静态的分配存储空间,数据存储在静态存储区中。在程序整个执行期间都不释放,生存期贯穿于程序执行的整个过程。
函数中的局部变量,如不专门声明为static存储类别,默认都是动态地分配存储空间的,我们在平时的声明变量的过程中auto都是默认省略的。
全局变量
全局变量也称为外部变量,是在函数的外部定义的,它的作用域为从变量定义处開始,到本程序文件的末尾。全局变量所有存放在静态存储区,在程序開始运行时给全局变量分配存储区,程序行完成就释放。在程序运行过程中它们占领固定的存储单元,而不动态地进行分配和释放;
假设外部变量不在文件的开头定义,其有效作用域仅仅限于定义处到文件终。
假设在定义点之前的函数想引用该外部变量,则应该在引用之前用keywordextern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就能够从“声明”处起,合法地使用该外部变量。其有效作用域就被拓展到从这个文件extern声明处到文件结束。
假设在全局变量声明的时候,前面加上keywordstatic,那么其它文件就不能再訪问和使用该变量,其有效作用域仅仅限于定义处到文件终。
局部变量是否能和全局变量重名
局部变量能和全局变量重名,可是局部变量会屏蔽全局变量。在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。
PS:这对extern声明的全局变量也一样。
---------------------------------------------------------------
一般全局变量存放在数据区,局部变量存放在栈区,
动态变量存放在堆区,函数代码放在代码区。
---------------------------------------------------------------
栈区是普通的栈数据结构,遵循LIFO后进先出的规则,局部变量安排在那里是ASM时就规定的,这样能够在一个函数结束后平衡堆栈,操作简单,效率高
堆(动态区)在这里应当叫堆栈(不要和数据结构中的堆搞混)是程序在编译时产生的一块用于产生动态内存分配使用的块,操作比較栈要麻烦很多,在分配时要推断最优的地址(防止产生没用的内存碎片(因为屡次的NEW和DELETE产生的夹在两块使用中内存中的空余小内存(不easy被分配))),分配和回收时的效率比栈低多了
---------------------------------------------------------------
栈是系统提供的功能,特点是高速高效,缺点是有限制,数据不灵活;而栈是函数库提供的功能,特点是灵活方便,数据适应面广泛,可是效率 >有一定减少。栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种。静态分配是编译器完毕的,比方自己主动变量(auto)的分配。动态分配由alloca函数完毕。栈的动态分配无需释放(是自己主动的),也就没有释放函数。为可移植>的程序起见,栈的动态分配操作是不被鼓舞的!堆空间的分配总是动态的,尽管程序结束时全部的数据空间都会被释放回系统,可是精确的申请内存/ 释放内存匹>配是良好程序的基本要素。
这是我对堆与栈收藏内容~
---------------------------------------------------------------
堆是程序猿管理的,栈是系统管理的.
---------------------------------------------------------------
---------------------------------------------------------------
---------------------------------------------------------------
另外关于静态和全局的一些问题:
静态变量的特点:
1、 一次存储:静态局部变量仅仅被初始化一次,下一次初始化依据上一次的结果值,有点相似于c++中类的静态成员变量,即不管该类型生成多少个实例对象,全部的对象共用一个静态变量,到这里就是不管这个函数调用多少次,该静态变量仅仅初始化一次,并没有由于超出其生存期而被销毁,仅仅是外部不可见而已,用个样例说明之:
void
fun1( int
v ) { static int
value = v;
static
int value =
v; } int
main( int
arc, char *args[
]) { fun1( 50 );
fun1(
100 ); } |
运行的结果是:value : 50
value : 50
说明在第二次调用fun1( )时的初始化value的採用的是上一次value的值,value在静态区的存储空间并没有由于fun1( )的结束而被释放,即体现了一次存储;
2、
作用域限定:静态修饰的作用域限定功能同一时候体如今函数与变量上;
a)
对于函数而言,不论什么用static修饰的函数,其作用域仅为当前源文件,而对外部来说这个函数是不可见的,即唯独和其在同一源文件里的函数才干调用这个静态函数;反过来说,假设一个函数只被同一源文件里的其它函数调用,那么这个函数应该声明为静态的,这样做的优点在于:能够一定程度上的解决不同源文件之间函数的命名冲突问题;
b)
对于变量而言,static修饰的全局变量,仅仅在当前源文件里有效,对外部不可见,外部文件不可以引用;
顾名思义,全局变量是指可以在全局引用的变量,相对于局部变量的概念,也叫外部变量;同静态变量一样,全局变量位于静态数据区,全局变量一处定义,多处引用,用keyword“extern”引用“外部”的变量。
全局变量也能够是静态的,在前面有过说明,静态全局变量的意义就是不让“外部”引用,是单个源文件中的全局变量,即是编译阶段的全局变量,而不是连接阶段的全局变量。
通过上面的分析,我们不难得出下面结论:
1、
静态函数与普通函数的差别在于:静态函数不能够被同一源文件以外的函数调用。
2、
静态局部变量与普通局部变量的差别在于:静态局部变量仅仅初始化一次,下一次初始化实际上是依旧是上一次的变量;
3、
静态全局变量与普通全局变量的差别在于:静态全局变量的作用域仅限于所在的源文件。
---------------------------------------------------------------
---------------------------------------------------------------
---------------------------------------------------------------
静态变量的类型说明符是static。
静态变量当然是属于静态存储方式,可是属于静态存储方式的量不一定就是静态变量,比如外部变量虽属于静态存储方式,但不一定是静态变量,必须由
static加以定义后才干成为静态外部变量,或称静态全局变量。对于自己主动变量,它属于动态存储方式。
可是也能够用static定义它为静态自己主动变量,或称静态局部变量,从而成为静态存储方式。
由此看来, 一个变量可由static进行再说明,并改变其原有的存储方式。
1. 静态局部变量
在局部变量的说明前再加上static说明符就构成静态局部变量。
比如:
static int a,b;
static float array[5]={1,2,3,4,5};
静态局部变量属于静态存储方式,它具有下面特点:
(1)静态局部变量在函数内定义,但不象自己主动变量那样,当调用时就存在,退出函数时就消失。静态局部变量始终存在着,也就是说它的生存期为整个源程序。
(2)静态局部变量的生存期虽然为整个源程序,可是其作用域仍与自己主动变量同样,即仅仅能在定义该变量的函数内使用该变量。退出该函数后,虽然该变量还继续存在,但不能使用它。
(3)同意对构造类静态局部量赋初值。若未赋以初值,则由系统自己主动赋以0值。
(4)对基本类型的静态局部变量若在说明时未赋以初值,则系统自己主动赋予0值。而对自己主动变量不赋初值,则其值是不定的。 依据静态局部变量的特点,
能够看出它是一种生存期为整个源程序的量。尽管离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用,并且保存了前次被调用后留下的值。
因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑採用静态局部变量。尽管用全局变量也能够达到上述目的,但全局变量有时会造成意外的副作用,因此仍以採用局部静态变量为宜
2.静态全局变量
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。
这两者在存储方式上并无不同。这两者的差别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件里都是有效的。
而静态全局变量则限制了其作用域, 即仅仅在定义该变量的源文件内有效,
在同一源程序的其他源文件里不能使用它。因为静态全局变量的作用域局限于一个源文件内,仅仅能为该源文件内的函数公用,因此能够避免在其他源文件里引起错误。从以上分析能够看出,
把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。因此static
这个说明符在不同的地方所起的作用是不同的。应予以注意。
静态变量
除范围之外,变量还有存活期,在这一期间变量可以保持它们的值。在应用程序的存活期内一直保持模块级变量和公用变量的值。可是,对于 Dim
声明的局部变量以及声明局部变量的过程,仅当过程在运行时这些局部变量才存在。通常,当一个过程运行完成,它的局部变量的值就已经不存在,并且变量所占领的内存也被释放。当下一次运行该过程时,它的全部局部变量将又一次初始化。
但可将局部变量定义成静态的,从而保留变量的值。在过程内部用 Static keyword声明一个或多个变量,其使用方法和 Dim
语句全然一样:
Static Depth
比如,以下的函数将存储在静态变量 Accumulate 中的曾经的运营总值与一个新值相加,以计算运营总值。
Function RunningTotal (num)
Static ApplesSold
ApplesSold = ApplesSold + num
RunningTotal = ApplesSold
End Function
假设用 Dim 而不用 Static 声明
ApplesSold,则曾经的累计值不会通过调用函数保留下来,函数仅仅会简单地返回调用它的那个同样值。
在模块的声明段声明
ApplesSold,并使它成为模块级变量,由此也会收到相同效果。可是,这样的方法一旦改变变量的范围,过程就不再对变量排他性存取。因为其他过程也能够訪问和改变变量的值,所以运营总值或许不可靠,代码将更难于维护。
声明全部的局部变量为静态变量
为了使过程中全部的局部变量为静态变量,可在过程头的起始处加上 Static keyword。比如:
Static Function RunningTotal (num)
这就使过程中的全部局部变量都变为静态,不管它们是用 Static、Dim 或 Private 声明的还是隐式声明的。能够将 Static 放在不论什么
Sub 或 Funtion 过程头的前面,包含事件过程和声明为 Private 的过程。