代码改变世界

C语言存储类型及各存储类型作用域和生存域比较

2015-10-30 13:57  SysTick  阅读(1273)  评论(0编辑  收藏  举报

c语言中的存储类型有`auto`, `extern`, `register`,`static` 这四种,存储类型说明了该变量要在进程的哪一个段中分配内存空间,可以为变量分配内存存储空间的有数据区、BBS区、栈区、堆区。

  1. 数据区  存放已初始化的全局变量、静态变量(全局和局部)、常量数据。
  2. BBS区  存放的是未初始化的全局变量和静态变量。   
  3. 栈区  由编译器自动分配释放,存放函数的参数值、返回值和局部变量,在程序运行过程中实时分配和释放,栈区由操作系统自动管理,无须程序员手动管理。
  4. 堆区  堆是由malloc()函数分配的内存块,使用free()函数来释放内存,堆的申请释放工作由程序员控制,容易产生内存泄漏。

 

  •   自动存储类型(`auto`)

自动存储类型修饰符指定了一个局部变量为自动的,这意味着,**每次执行到定义该变量的语句块时,都将会为该变量在内存中产生一个新的拷贝,并对其进行初始化**。实际上,如果不特别指明,局部变量的存储类型就默认为自动的,因此,加不加`auto`都可以。

1     //函数默认的存储类型也是auto。
2     int main()
3     {
4         //在这个例子中,m的声明无论是否包含auto,执行的效果都是一样的,即默认为auto,
5         auto int m = 99;  
6         printf("%d\n", m);
7         return 0;
8     }    

 

  • 静态存储变量(`static`)

被声明为静态类型的变量,无论是全局的还是局部的,都存储在数据区中,其生命周期为整个程序,如果是静态局部变量,其作用域为一对{}内,如果是静态全局变量,其作用域为当前文件。静态变量如果没有被初始化,则自动初始化为0。**静态变量只能够初始化一次,在随后的运行过程中,都将保持程序上一次使用的值。**

 1     //对比auto类型变量和static类型的变量在执行过程中的差别
 2     #include <stdio.h>
 3     int main()
 4     {
 5         int i;
 6         for(i = 0; i < 3; i++)
 7         {
 8             auto int m = 20;
 9             static int n = 20;
10             printf("m%d is %d,    ",i,m);
11             printf("n%d is %d;",i,n);
12             printf("\n");
13             m++;
14             n++;
15         }
16         return 0;
17     }

 

运行结果:

    m0 is 20,    n0 is 20;  
    m1 is 20,    n1 is 21;  
    m2 is 20,    n2 is 22


  •  外部存储变量(`extern`)

  通常,`extern`都是用于声明在另一个转换单元中定义的变量。即`extern`用来声明在当前文件中引用在当前项目中的其它文件中定义的全局变量。如果全局变量未被初始化,那么将被存在BBS区中,且在编译时,自动将其值赋值为0,如果已经被初始化,那么就被存在数据区中。全局变量,不管是否被初始化,其生命周期都是整个程序运行过程中,为了节省内存空间,在当前文件中使用extern来声明其它文件中定义的全局变量时,就不会再为其分配内存空间。

  • 寄存器存储类型(`register`)

声明为寄存器存储类型的变量,除了程序无法得到其地址外,其余都和自动变量一样。声明为register的变量在由内存调入到CPU寄存器后,则常驻在CPU的寄存器中,因此访问register变量将在很大程度上提高效率,因为省去了变量由内存调入到寄存器过程中的好几个指令周期。 

各存储类型比较


从这个表中可以看出,C程序的标识符作用域有三种:*局部、全局、文件*。标识符的作用域决定了程序中的哪些语句可以使用它,换句话说,就是标识符在程序其他部分的可见性。通常,标识符的作用域都是通过它在程序中的位置隐式说明的。