变量的存储类型:
自动型(auto)
存储区域:内存堆栈区 (系统默认内部变量为auto)
寄存器型 ( register )
存储区域:CPU的通用寄存器 (一般C语方允许定义二个左右为宜) [一般在函数中定义(内部变量)]
静态型( static )
存储区域:内存的数据区 ( 在程序开始时就分配了固定的内存,程序结束时才释放内存 )
外部参照型 ( extern ) 专用于多个编译单位数据传送。
static的讲解
全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式,静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。 从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域, 限制了它的使用范围。 static函数与普通函数作用域不同。仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件。
外部变量和static内部变量的区别
外部参照型变量不允许进行初始化,其它的可以进行初始化。
外部变量只能定义为无存储类型或静态型
被说明为static存储型的内部变量是全局变量,在整个程序运期存都存在,它的作用域只是所定义的函数或复合语句
外部变量是不能重命名的,内部变量可以在不同的函数或复合语句中重命名,包括static存储类型的内部变量(因为它们彼此的作用域是不同的)。
外部变量总是全局变量
外部变量和全局变量是对同一类变量的两种不同角度的提法。全局变是是从它的作用域提出的,外部变量从它的存储方式提出的,表示了它的生存期。
外部变量有两种声明方式:定义性声明和引用性声明。
定义性声明是为了创建变量,即需为变量分配内存。引用性声明是为了建立变量与内存单元之间的关系,表示要引用的变量已在程序源文件中其他地方进行过定义性声明。定义性声明只能放在函数外部,而引用性声明可放在函数外部,也可放在函数内部。
externintb;//引用性声明,也可放在函数fun中
voidfun()
{
printf("d%",b);//输出
}
externintb=5;//定义性声明,可以省略关键字extern
外部静态变量/函数
在C中static有了第二种含义:用来表示不能被其它文件访问的全局变量和函数。, 但为了限制全局变量/函数的作用域, 函数或变量前加static使得函数成为静态函数。但此处“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件(所以又称内部函数)。注意此时, 对于外部(全局)变量, 不论是否有static限制, 它的存储区域都是在静态存储区, 生存期都是全局的. 此时的static只是起作用域限制作用, 限定作用域在本模块(文件)内部.
使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名。
static的局部变量和全局变量区别
static的局部变量改变存储域,static的全局变量改变作用域(只能在源程序的一个源文件中使用)
在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,全局变量不起作用。
变量的存储方式可分为“静态存储”和“动态存储”两种。
静态存储变量通常是在变量定义时就分定存储单元并一直保持不变, 直至整个程序结束。(全局变量即属于此类存储方式。)
动态存储变量是在程序执行过程中,使用它时才分配存储单元, 使用完毕立即释放。 典型的例子是函数的形式参数,在函数定义时并不给形参分配存储单元,只是在函数被调用时,才予以分配, 调用函数完毕立即释放。如果一个函数被多次调用,则反复地分配、 释放形参变量的存储单元。
静态存储变量是一直存在的, 而动态存储变量则时而存在时而消失。
寄存器变量
C语言提供了另一种变量,即寄存器变量。这种变量存放在CPU的寄存器中,使用时,不需要访问内存,而直接从寄存器中读写, 这样可提高效率。寄存器变量的说明符是register。 对于循环次数较多的循环控制变量及循环体内反复使用的变量均可定义为寄存器变量。
local小结:
局部变量只在块范围内有效,“块”包括自定义{}和函数,包括{}内临时(自动)变量,函数形参和函数体内临时(自动)变量。
内存管理经典笔试题之Test()->GetMemory():
--------------------------------------------------------------
voidGetMemory1(char*p)
{
p=(char*)malloc(100);/*形参指针变量_p值改变*/
}
voidTest1(void)
{
char*str=NULL;
GetMemory1(str);/*实参指针变量str值仍为NULL*/
strcpy(str,"helloworld");/*非法内存访问导致程序崩溃*/
printf(str);
}
--------------------------------------------------------------
char*GetMemory2(void)
{
char*p="helloworld";/*指针指向静态常量区(.rodata),不允许修改*/
returnp;
}
voidTest2(void)
{
char*str=NULL;
str=GetMemory2();
printf(str);/*允许只读访问*/
}
--------------------------------------------------------------
char*GetMemory3(void)
{
charp[]="helloworld";/*指针p为栈自动变量*/
returnp;
}/*栈自动变量将在此释放*/
voidTest3(void)
{
char*str=NULL;
str=GetMemory3();/*str非NULL,但其所指栈区变量可能被清除*/
printf(str);/*可能乱码*/
}
--------------------------------------------------------------