【IOS 开发学习总结-OC-7.3】C 语言特性——动态存储与静态存储

来源:互联网 发布:linux spark 编辑:程序博客网 时间:2024/05/18 17:55

从变量的存储机制来看,C 语言的变量可分为动态存储变量与静态存储变量。

变量按存储机制的分类

动态存储:程序在运行期间根据需要动态分配内存的存储方式。
静态存储:程序在运行开始就分配固定内存的存储方式。

就C 程序运行的内存来说,大致可分为3个部分:程序区,静态存储区(在运行开始就分配固定内存,直到程序运行结束才会释放内存),动态存储区(运行期间根据需要动态分配内存)。C 的变量,要么放在静态存储区,要么放在动态存储区。

静态存储区存放什么样的变量?

存放2类变量:全局变量和 static 修饰的局部变量。
不管是那种外部变量,外部全局变量或者内部全局变量(static 修饰的,只在当前源文件中有效的全局变量),都存放在静态存储区的。

动态存储区存放什么样的数据?

主要存放3类数据:函数的形参变量;非 static 的局部变量;函数执行的现场数据以及返回地址等。
可以在定义变量时指定变量的存储类别,C语言支持如下几种存储类别。

  • auto: 指定该变量采用自动存储机制——局部变量默认采用这种方式,对定义局部变量,auto 关键字可以忽略。
  • static:指定局部变量存到静态存储区。这样该变量所占空间会一直保存到程序退出。
  • register:指定该变量存放到寄存器内。
  • extern:用于声明外部变量。

静态局部变量和普通局部变量的区别

示例代码:

#import <Foundation/Foundation.h>void fac(int n){    auto int a = 1;    // 定义静态局部变量,每次函数调用结束后,都会保存该变量的值    static int b = 1;    // a(每次调用时a总是等于1)的值加上n    a += n;    // b(b变量可以保留上一次调用的结果)的值加上n    b += n;    NSLog(@"a的值为:%d , b的值为%d" , a , b);}int main(int argc , char * argv[]){    @autoreleasepool{        // 采用循环调用了fac()函数4次        for(int i = 0 ; i < 4 ; i++)        {            fac(i);        }    }}

每次调用 fac() 函数时,变量 a 的值总是1,而对于 static 修饰的变量而言,只有第一次调用该函数的时候才会等于初始值,以后该变量都会保存改动后的结果。
贴士:
实际上,程序员也可以不对 static 变量指定初始值,那么系统会在编译时自动为 static 变量分配默认的初始值。默认初始值都是广义的0.对整型 static 局部变量,该初始值总是0;对于浮点型的 static 局部变量,初始值总是0.0;对于指针型的 static 局部变量,初始值总是0x0(未指向任何有效对象的指针)
利用 static 变量的特性,轻松计算阶乘。代码如下:

#import <Foundation/Foundation.h>int fac(int n){    // static变量,第一次运行时该变量的值为1    // f可以保留上一次调用函数的结果    static int f = 1;    f = f * n;    return f;}int main(int argc , char * argv[]){    @autoreleasepool{        // 采用循环,控制调用该函数7次        for(int i = 1 ; i < 8 ; i++)        {            NSLog(@"%d的阶乘为:%d", i , fac(i));        }    }}

特别指出:
虽然静态局部变量可以在函数调用结束后仍然在,但只能在本函数在此调用时访问该变量的值,其他函数不能访问该静态局部变量的值。

什么时候使用静态局部变量?

应该慎重使用静态局部变量,因为静态局部变量会一直占据固定的内存。考虑使用静态局部变量的情况如下:

  1. 需要变量能保留上次调用结束时的值。
  2. 希望变量只被初始化一次,以后只是被引用,而不希望对其重新赋值。
0 0
原创粉丝点击