cpp储存类别,链接,内存管理
1.作用域
作用域描述程序中可以访问标识符的区域。一个c变量的作用域可以是块作用域,函数作用域,函数原型作用域,或文件作用域。(常用的是块作用域)
1.块作用域是用一对花括号括起的代码。
2.函数原型作用域用于函数原型中的形参名。如
int f(int a,double b);
3.函数作用域仅使用在goto语句的标签。意味着即使一个标签首次出现在函数内层块中,它的作用域也能够延申整个函数。
4.变量定义在函数外面具有文件作用域,
2.链接
c变量有3中属性;外部链接,内部链接,或无链接。具有块作用域,函数作用域或函数原型作用域的变量都是无链接变量。意味着这些属于它们定义他们的块,函数或原型私有。具有文件作用域的变量可以是外部链接或内部链接。外部链接可以在多文件程序中使用,内部链接变量只能在一个翻译单元使用。
3.存储类别
在cpp上,列出了以下五种存储类型:
1.自动变量:
关键词auto.属于自动存储类别的变量具有自动存储期,块作用域且无链接,默认情况下,声明在块或函数头中的任何变量都属于自动存储类别。可以加上auto关键词.在块作用域中声明,具有自动存储期,即程序进入该块时变量存在,退出该块时变量被销毁.
如下所示
int f(int a) //定义f函数,a为形参
{
auto int b,c=3; //定义b和c为整型的自动变量
┆
}
存储类别auto和数据类型int的顺序任意。关键字auto可以省略,如果不写auto,则系统把它默认为自动存储类别,它属于动态存储方式。程序中大多数变量属于自动变量。本书前面各章所介绍的例子中,在函数中定义的变量都没有声明为auto,其实都默认指定为自动变量。在函数体中以下两种写法作用相同:
① auto int b,c=3;
② int b,c=3;
2.寄存器变量:
关键词为register,其性质与自动变量很相似,块作用域,自动存储期.但是因为它被存储在寄存器中而不是内存中,所以无法获取它的地址.与普通变量相比,访问和处理这些变量的速度要更快。同时要注意的是,声明寄存器变量只是一种请求,最终是否将该变量存在寄存器中则是由编译器来决定.但无论是否被存入寄存器,该变量都无法获取地址.
如,可以将例4.14中的fac函数改写如下:
如可以将例4.14中的fac函数改写如下:
int fac(int n)
{
register int i,f=1; //定义i和f是寄存器变量
for(i=1;i<=n;i++) f=f*i;
return f;
}
定义f和i是存放在寄存器的局部变量,如果n的值大,则能节约许多执行时间。
在程序中定义寄存器变量对编译系统只是建议性(而不是强制性)的。当今的优化编译系统能够识别使用频繁的变量,自动地将这些变量放在寄存器中。
3.静态变量无链接:
在块内用关键字static声明变量,具有块作用域,但它的存储期是静态的,也就是说,在该变量被创建后,程序停止运行才会释放该变量.在循环中,但程序再一次运行到该声明时,会跳过去.自动初始化为0.
例4.12 静态局部变量的值。
#include <iostream>
using namespace std;
int f(int a) //定义f函数,a为形参
{
auto int b=0; //定义b为自动变量
static int c=3;//定义c为静态局部变量
b=b+1;
c=c+1;
return a+b+c;
}
int main( )
{
int a=2,i;
for(i=0;i<3;i++)
cout<<f(a)<<″ ″;
cout<<endl;
return 0;
}
运行结果为
7 8 9
4.静态变量与外部链接:
关键词为extern.作为外部变量作用域自然是文件,静态存储期,感觉叫全局变量比较舒服,也比较熟悉,这种变量在所有块外面声明,可以在同一个程序不同翻译单元(很奇怪的名字,反正就是不同的文件)中作用.如果要在一个文件中使用另一个文件的全局变量,要用关键字extern.自动初始化为0.
例4.14 用extern对外部变量作提前引用声明,以扩展程序文件中的作用域。
#include <iostream>
using namespace std;
int max(int,int); //函数声明
void main( )
{
extern int a,b;//对全局变量a,b作提前引用声明
cout<<max(a,b)<<endl;
}
int a=15,b=-7;//定义全局变量a,b
int max(int x,int y)
{
int z;
z=x>y?x:y;
return z;
}
运行结果如下:
15
在main后面定义了全局变量a,b,但由于全局变量定义的位置在函数main之后,因此如果没有程序的第5行,在main函数中是不能引用全局变量a和b的。现在我们在main函数第2行用extern对a和b作了提前引用声明,表示a和b是将在后面定义的变量。这样在main函数中就可以合法地使用全局变量a和b了。如果不作extern声明,编译时会出错,系统认为a和b未经定义。一般都把全局变量的定义放在引用它的所有函数之前,这样可以避免在函数中多加一个extern声明。
5.静态变量与内部链接:
这个与全局变量的区别在于声明时需要加上static关键字,同时无法被其他文件使用.自动初始化为0.
***存储类别小结
存储类别 | 存储期 | 作用域 | 链接 | 声明方式 |
---|---|---|---|---|
自动 | 自动 | 块 | 无 | 块内 |
寄存器 | 自动 | 块 | 无 | 块内,使用关键字registe |
静态外部链接 | 静态 | 文件 | 外部 | 所有函数外 |
静态内部链接 | 静态 | 文件 | 内部 | 所有函数外,使用关键字static |
静态无链接 | 静态 | 块 | 无 | 块内 |
**4.内存管理**
函数 | 描述 |
---|---|
*calloc(int num, int size); | 在内存中动态地分配 num 个长度为 size 的连续空间,并将每一个字节都初始化为 0。所以它的结果是分配了 num*size 个字节长度的内存空间,并且每个字节的值都是0。 |
free(void *address); | 该函数释放 address 所指向的内存块,释放的是动态分配的内存空间。 |
*malloc(int num); | 在堆区分配一块指定大小的内存空间,用来存放数据。这块内存空间在函数执行完成后不会被初始化,它们的值是未知的。 |
*realloc(void *address, int newsize); | 该函数重新分配内存,把内存扩展到 newsize。 |
上述函数多用于链表中,均处于<stdlib.h>中。