static变量与全局变量
一、程序的内存分配
一个由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和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。
static函数与普通函数有什么区别
用static修饰的函数,本限定在本源码文件中,不能被本源码文件以外的代码文件调用。而普通的函数,默认是extern的,也就是说,可以被其它代码文件调用该函数。
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。普通 函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。因此定义静态函数有以下好处:
<1> 其他文件中可以定义相同名字的函数,不会发生冲突。
<2> 静态函数不能被其他文件所用。
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
答:
1) 全局变量(外部变量)的说明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。
2) 从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。
3) static函数与普通函数作用域不同,仅在本文件。只在当前源文件中使用的函数应该说明为内部函数(static),内部函数应该在当前源文件中说明和定义。对于可在当前源文件以外使用的函数,应该在一个头文件中说明,要使用这些函数的源文件要包含这个头文件
综上所述:
static全局变量与普通的全局变量有什么区别:
static全局变量只初使化一次,防止在其他文件单元中被引用;
static局部变量和普通局部变量有什么区别:
static局部变量只被初始化一次,下一次依据上一次结果值;
static函数与普通函数有什么区别:
static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝
static变量与全局变量相关推荐
- 对C语言 static作用——修饰 变量(全局变量/局部变量)、函数
*******************************概念******************************************** ********************** ...
- php 全局 静态变量,php的static关键字和全局变量
1.全局变量[其不属于面向对象的思想,因为其放在对象之外的],面向对象有一个特点,其实封装的,php希望其所有的成员都应该放在类中:php的面向对象是基于面向对象的,不是纯粹面向对象的:也就是其可以面 ...
- 【C++】C/C++ 中 static 的用法全局变量与局部变量
C/C++ 中 static 的用法全局变量与局部变量 目录 1. 什么是static? 1.1 static 的引入 1.2 静态数据的存储 2. 在 C/C++ 中static的作用 2.1 总的 ...
- 局部变量和static变量
局部变量:指在程序中,只在特定过程或函数中可以访问的变量,是相对于全局变量而言的.在C++.C#.Ruby这些面向对象语言中,一般只使用局部变量.在面向对象编程中现在普遍采用的是软件开发方法,因此无需 ...
- c++ static用法,全局变量,与别的语言不一样
C/C++ 中 static 的用法全局变量与局部变量 (1)在修饰变量的时候,static 修饰的静态局部变量只执行初始化一次,而且延长了局部变量的生命周期,直到程序运行结束以后才释放. (2)st ...
- 一种安全的static变量Get/Set方式
目的:避免static变量是个文件内可见的全局变量 Get: std::atomic<bool>* GetGraphVerboseStepLr() {static std::atomic& ...
- (转)static 变量
一. static 变量 static变量大致分为三种用法 1. 用于局部变量中,成为静态局部变量. 静态局部变量有两个用法,记忆功能和全局生存期. 2. 用于全局变量,主要作用是限制此全局变量被其他 ...
- 关于static变量,请选择下面所有说法正确的内容
若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度 若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度 设计和使用访问动态 ...
- inline函数包涵static变量,调用时是否会有多份拷贝
inline int static_test() { static int i =0; ... } inline 代表编译时代码拷贝,也就有多份副本了, ...
最新文章
- Visual Studio2005奇怪的bug及解决【月儿原创】
- (未完)httpd进程数查询,prefork模式修改apache最大连接数
- JSON字符串的解析
- 【若依(ruoyi)】自定义layer
- 海口只有阳光沙滩?错,人家还是“最佳智慧城市”
- Python中的条件选择和循环语句
- Markdown简介和基本语法
- 2018蓝桥杯省赛---java---B---1(第几天)
- 本月与上月对比数据叫什么_动态轨控数据分析:2019-11
- flex----其他交互设计
- JProfiler 解决 Java 服务器的性能跟踪
- 使用SQL Storage Compress压缩SQL Server 数据库文件
- Vue.js 学习笔记 五 常用的事件修饰符
- SVPWM算法原理及详解
- stvd能编辑c语言吗,STVD自动生成的stm8_interrupt_vector.c中几个疑问
- 微信公众号服务号申请注册教程
- 「AR裸眼插画」零基础入门级教程来啦
- greenplum 数据导入 导出
- 【腾讯WeTest干货分享】高并发性能调试经验分享
- 模拟喷泉码(入门二):Seamless Rate Adaptation for Wireless Networking
热门文章
- I - [登峰造极-2016]_QAQ字符串
- Unity简单操作:HDR(一) 给Camera开启HDR
- MySQL导入selectclass文件_MySQL执行Select语句将结果导出到文件的方法 – 疯狂的蚂蚁...
- JAVA基础之方法的递归调用
- EXOduino开源手外骨骼有几个自由度?
- 阿里云ecs和域名的购买,绑定,备案教程
- java treeview控件,TreeView下载
- windows C++客户端开发技术栈(C++应用开发技术栈)
- Android通过SystemProperties类查看系统参数
- iPhone 几年换一次比较合?---转自百度新闻|数码千机会