局部变量,静态局部变量,全局变量,静态全局变量在内存中的存放区别

来源:互联网 发布:nginx static 配置 编辑:程序博客网 时间:2024/06/05 11:52

概念

首先得明白局部变量,静态局部变量,全局变量,静态全局变量这几个概念,以下面程序举例:

//main.cpp int a = 0; //全局变量static int b=0;//静态全局变量main() { int c; //局部变量static int d;//静态局部变量 }
  • 全局变量:具有全局作用域,全局变量只需在一个源文件中定义,就可以作用于所有的源文件。
  • 静态全局变量:具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被 static 关键字修饰过的变量具有文件作用域。
  • 局部变量:具有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
  • 静态局部变量:具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在。

存储方式

网上关于内存划分,有几种说法,我选择一种我比较接受的说法。
- 代码区,是编译器生成的一个exe区段,拥有可读和可执行属性。存放函数体的二进制代码。
- 栈区,低地址(小于exe基地址),拥有可读写属性,exe中没有对应的区段,系统加载dll时自动生成,由于内存地址使用方式从大往小减,所以数量有限,尽量不要定义过大的数组变量。 const的局部变量也是放在栈里的,而不是放在常量区。由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
- 堆区,就是malloc和new之类的内存所在区段,拥有可读写属性,exe中没有对应的区段,系统加载dll时自动生成,首先是利用栈区地址下面的区段,也是低地址,当用完了,会自动分配稍微高一点地址(大于exe基地址)。 malloc和new都在这里分配内存。一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
- 全局数据区,是编译器生成的一个exe区段,拥有可读写属性,初始和未初始化的全局和静态变量都放在这里。全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 程序结束后由系统释放。
- 常量区,是编译器生成的一个exe区段,只有可读属性,比如char s = ” hello world” ,这时候” hello world” 就在常量区,由于没有可写属性,所以修改内容会出错,另外全局的const变量也放在常量区里。

栈和堆的申请方式

栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,
会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

栈和堆的存储内容

栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

0 0
原创粉丝点击