在c语言中,存储区可以分成代码区,全局区,常量区,栈,堆;如下图所示:
全局区 :主要存储全局变量和static变量。
常量区:存放常量的地方。
堆:用户申请的内存区,用编译器提供的函数new或malloc申请。要注意内存泄露的问题
栈:系统自动给局部变量分配的内存区。
extern关键词:extern修饰全局变量glovar时,表明glovar可以被其他模块的函数使用;
extern修饰函数是,表明函数可以被其他模块的函数调用;
static关键词:static修饰局部变量var时,表明var在函数调用结束时不销毁,函数在此被调用时,不对VAR 再次定义,使用上次调用结束时的值,他的生命期:从第一次调用开始,到main结束;
static修饰全局变量glovar时,表明glovar不能够被其他模块的函数使用;
static修饰函数是,表明函数不能够被其他模块的函数调用;
voltile:表明变量可能在另外的进程修改,因此每次使用时,必须重新从内存读取。
全局变量,局部变量,形参何时分配内存:
全局变量:在编译时分配,在main结束时释放;
局部变量、形参:在函数调用时分配,在函数返回时释放;
static局部变量:在函数第一次第一次调用时分配,在main结束时释放,在两者之间不再对static局部变量 分配内存。
申请效率的比较:
栈由系统自动分配,速度较快。但程序员是无法控制的。
堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.
堆和栈中的存储内容
栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
存取效率的比较
char s1[] = "aaaaaaaaaaaaaaa";
char *s2 = "bbbbbbbbbbbbbbbbb";
aaaaaaaaaaa是在运行时刻赋值的;
而bbbbbbbbbbb是在编译时就确定的;
但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。
小提示:
(1)如果一个函数中的一个变量被声明为静态,那么这个变量就会被静态的分配内存空间,但是它仅在函数内可见,但是变量不会在每次函数调用时都被创建。对程序运行期间可能反复调用的函数,又希望对其他函数隐藏该变量,用静态局部变量。若不必对其他函数隐藏用全局变量。
(2)非必要时尽量不要使用全局变量,原因两点:1.外部变量破坏函数的独立性。2.全局变量在执行过程中始终占用存储单元。
(3)register寄存器变量,用于提高被频繁使用的局部变量的运行效率,但是不能定义任意多个寄存器变量,对Intel体系CPU寄存器个数在6~16个之间。只有局部自动变量和形式参数才能被定义为寄存器变量。全局变量和局部静态变量都不能定义为寄存器变量。
(4)用extern声明外部变量时,类型标识符是可以省略的。如extern int x;写成extern x;
(5)static修饰函数时,与静态变量不同,static不是指存储方式,而是指函数作用域仅局限于本文本。