在C语言中,有5种不同的存储类型,即存储类。在介绍存储类之前,需要首先简单介绍几个术语。如下:
作用域:描述程序中可以访问一个标识符的一个或多个区域。一个C变量的作用域可以是代码块作用域、函数原型作用域、或者文件作用域。代码块作用域是在代码块中定义的变量,该变量的作用范围从代码块中变量的定义开始到代码块结束;函数原型作用域从变量定义开始到原型声明的末尾,这就意味着编译器在处理一个函数原型的参数时,只是关心该参数的类型,所以声明一个函数int sum(int x,int y)和int sum(int,int)是一样的;而一个在所用函数之外定义的变量具有文件作用域,具有文件作用域的变量从他定义开始到包含该定义文件的结尾处都是可见的,也被称作全局变量。代码说话:
1 #include<stdio.h> 2 3 int x = 0; //x具有文件作用域,在这程序中结尾之前都是可见的 4 int sum(int m,int n);//m,n具有函数原型作用域,只在申明处可见 5 6 int main(int argc, char* argv[]) 7 { 8 int y = 1;//y具有代码块作用域,只在该代码块中可见 9 }
存储时期:一个C变量有以下两种存储时期十一:静态存储时期和自动存储时期。所谓静态存储时期,就是一个变量在程序执行期间一直存在,上文所说的具有文件作用域的变量就属于静态存储;对于自动存储时期,则对应上述所说的具有代码块作用域的变量,当程序进入定义这些变量的代码块时,将自动为这些变量分配内存,退出这个代码块时,这些变量所占的内存将会自动被释放。
链接:链接分为外部链接,内部链接,以及空链接。具有代码块作用域或者函数原型的变量有空链接。具有文件作用域的变量可能有内部链接或者外部链接。区别内部链接和外部链接是由static决定。内部链接由static关键字修饰,表明该变量可以在一个文件的任何地方使用,外部链接没有static修饰,表明该链接可以在一个多文件程序的任何地方使用。
1 int x = 10; //文件作用域,外部链接 2 static int y = 11; //文件作用域,内部链接 3 4 int main(){ 5 ...... 6 }
下面是5中存储类的对比表格:
说到这里要介绍一个关键字extern。extern表明你在声明一个已经在别处定义了的变量。下面是几种extern的使用:
Example.h:
1 int z = 10;
源程序:
1 #include<stdio.h> 2 #include "Example.h" 3 int x = 0; 4 5 int main(int argc, char* argv[]) 6 { 7 extern int x; //可选的二次声明,我们一般直接使用x,而不采用这种方式 8 extern int z; //z在Example.h中定义,使用extern之后,便可以在这个文件中使用z 9 10 }
同理,函数也可以这样使用。
对于内存分配,我们讲的是malloc()函数,malloc()函数可以在程序运行时分配更多的内存。它接受一个参数:所需内存字节数。直接上代码:
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 5 int main(int argc, char* argv[]) 6 { 7 int * ptr; 8 9 ptr = (int *)malloc(20 * sizeof(int));//类型指派(int *)在C中是可选的,但是在C++中是必须的 10 if(ptr == NULL){ 11 printf("内存不足,无法动态创建指定大小的数组."); 12 exit(EXIT_FAILURE); 13 } 14 15 printf("Before memset():"); 16 for (;i < 20;i++) 17 { 18 printf("%d,",ptr[i]); 19 } 20 21 memset(ptr,0,20*sizeof(ptr)); 22 printf(" After memset():"); 23 24 for (i = 0;i < 20;i++) 25 { 26 printf("%d,",ptr[i]); 27 } 28 29 printf(" Init:"); 30 31 for (i = 0;i < 20;i++) 32 { 33 ptr[i] = i; 34 } 35 36 for (i = 0;i < 20;i++) 37 { 38 printf("%d,",ptr[i]); 39 } 40 41 free(ptr); 42 printf(" free() "); 43 }
上面的例子使用malloc()函数创建了20个大小为int类型值的空间,如果创建成功,那么该函数会返回那块内存第一个字节的地址并且赋给int类型指针ptr。接下来就可以像使用数组名一样使用它了。malloc()函数分配内存之后不会对其进行初始化,与它相似的还有一个函数calloc()。后者接受两个参数,然后进行创建内存。但是他和malloc()函数不同的是,它会将申请的内存全部初始化为0。不过我们一般不使用calloc()函数申请内存,因为它初始化内存会浪费时间。在上面的程序中,我们初始化使用了函数memset()。
当我们使用malloc()或者calloc()函数动态申请内存之后,在使用完毕之后,最好使用free()函数来释放分配的内存。不然可能会引起"内存泄露"。
最后再补充一句:程序所需静态内存数量在编译时就决定了,静态数据在程序载入内存时就被载入了内存。