转:http://blog.163.com/zhangkai-@126/blog/static/312636552011101510416242/

一、程序的内存分配

一个由C/C++编译的程序占用的内存分为以下几个部分:

1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3、全局区(静态区)(static)— 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后有系统释放

4、文字常量区 — 常量字符串就是放在这里的。 程序结束后由系统释放。

5、程序代码区 — 存放函数体的二进制代码。

二、例子程序

//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b;// 栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; 123456\0";//在常量区,p3在栈上。
static int c =0; //全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
//分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456"); //123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。}

三、从作用域看:

全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量。

局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。

静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。

静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。

从分配内存空间看:
全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。

从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的。

四、总的来说就是:

1、生存周期不同
2、作用范围不同
3、分配方式不同

----------------------------------------------

再来看下堆和栈的不同:

1、分配方式不同;
2、空间大小不同;
3、分配效率不同;
4、能否产生碎片不同;
5、生长方向不同;

1、分配方式不同

栈:
由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间
堆:
需要程序员自己申请,并指明大小,在c中malloc函数
如p1 = (char *)malloc(10);
在C++中用new运算符
如p2 = (char *)new(10);
但是注意p1、p2本身是在栈中的。

2、 空间大小不同

一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M。

3、分配效率

栈 是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执 行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考 数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的 内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

4、碎片问题

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

对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先 进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出。

5、生长方向

对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存 的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈 的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。

转载于:https://www.cnblogs.com/smilefortoday/p/4031309.html

全局变量、局部变量、静态全局变量、静态局部变量在内存里的区别(转)相关推荐

  1. C/C++ 全局变量和局部变量在内存里的区别?堆和栈

    一.预备知识-程序的内存分配 一个由c/C++编译的程序占用的内存分为以下几个部分  1.栈区(stack)- 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈 ...

  2. 局部变量,静态局部变量,全局变量,静态全局变量在内存中的存放区别(转)...

    我们先来看内存中的几大区:  内存到底分几个区? 下面有几种网上的理解,我整理一下: 一: 1.栈区(stack)- 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构 ...

  3. 静态局部变量和全局变量的区别!

    静态局部变量和全局变量的区别! C++变量根据定义位置的不同,具有不同的作用域,作用域可分为6种:全局作用域,局部作用域,语句作用域,类作用域,命名作用域和文件作用域. 1.从作用域看: (1)全局变 ...

  4. 全局变量、静态全局变量、静态局部变量和局部变量的区别

    static和const都是C++中比较麻烦的东西,只要是太容易混淆他们的作用,之前对static做过点总结,但是不全面,还有很多小的错误,现在整理一下: 变量可以分为:全局变量.静态全局变量.静态局 ...

  5. 局部变量、全局变量、堆、堆栈、静态和全局

    一般全局变量存放在数据区,局部变量存放在栈区, 动态变量存放在堆区,函数代码放在代码区. ------------------------------------------------------- ...

  6. 【C++】局部变量、全局变量、静态变量与动态对象的性质

    [fishing-pan:https://blog.csdn.net/u013921430转载请注明出处] 概述 局部变量 在一个函数内部定义的变量(包括函数形参)是局部变量. 全局变量 在函数外定义 ...

  7. 全局变量、局部变量、静态全局变量、静态局部变量的区别

    文章转载至全局变量.局部变量.静态全局变量.静态局部变量的区别 C++变量根据定义位置的不同,具有不同的作用域,作用域可分为6种:全局作用域,局部作用域,语句作用域,类作用域,命名作用域和文件作用域. ...

  8. C|C++中的静态全局变量,静态局部变量,全局变量,局部变量的区别

    static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 面向过程设计中的static 全 ...

  9. 【函数的定义、调用(嵌套调用、递归调用)、声明、函数的分类(有无返回值、有无参数)、变量(自动变量与静态变量、局部变量与全局变量、只读变量)】(学习笔记7--函数)

    第一篇博文,打卡新星计划第三季3.4~4.4,希望能有质的飞跃,顶峰相见 一.自定义函数 1.函数的定义 函数在使用前也需要定义,定义的格式如下: 数据类型 函数名([数据类型 参数1],[数据类型 ...

最新文章

  1. EL:谁说N素含量高就不固氮了(本研究反而“多多益善”)
  2. mysqlbinlog查看 binlog日志报错mysqlbinlog: unknown variable 'default-character-set=utf8mb4'
  3. 腾讯-004-两个排序数组的中位数
  4. 解读Scorm(0):标准
  5. java第七章第九题_Java2程序设计基础第七章课后习题
  6. mysql 优化器提示_Mysql查询优化器
  7. JS版的bin2hex和hex2bin,支持汉字
  8. 数据同步工具简单介绍
  9. tcgames使用有延迟_Tcgames下载使用方法
  10. 观点|蚂蚁金服玉伯:我们是如何从前端技术进化到体验科技的?
  11. 使用Hibernate中save方法时由于设置的id的增长方式为assigned报错处理和
  12. 虚拟化技术介绍 hypervisor简介
  13. 全同态加密(FHE):BV方案、密钥切换、模约化、自举
  14. mysql同张表关联多次查询_MySQL多次单表查询和多表联合查询
  15. c语言选择结构作用,c语言选择结构程序设计教案
  16. 计算机提示无法识别usb,电脑提示“无法识别的USB设备”如何解决?
  17. JQuery中append(function(index,html)),appendTo(),after(function(index,html)),clone()方法
  18. maven shade 插件的小插曲
  19. 第四周——爬虫入门 Day3 7.20
  20. 已知两点获取单位向量 和 单位垂直向量

热门文章

  1. 计算机办公实用技能项目实践教程,计算机常用办公软件应用/21世纪计算机科学与技术实践型教程...
  2. 面对大规模 K8s 集群,如何先于用户发现问题?
  3. Service Mesh 最火项目 Istio 分层架构,你真的了解吗?
  4. Linux 父进程 子进程 回收,回收 fork() 的子进程
  5. Postman响应断言
  6. html5实现关灯效果,《第41天:JQurey - 关灯效果》
  7. 湖北经济学院法商学院计算机分数线,湖北经济学院法商学院
  8. 为什么dw预览不了php文件,dreamweaver为什么添加不了预览浏览器
  9. mariadb 没有mysql表_数据未插入mySQL表(MariaDB)
  10. jsp mysql驱动程序_JSP通过JDBC驱动MySQL数据库方法