求助 求助 !!局部变量使用了未初始化的局部变量一定要在同一个作用域吗

预备知识—程序的内存分配 
一个甴C/C++编译的程序占用的内存分为以下几个部分 

  • 栈区(stack)— 由编译器自动分配释放存放函数的参数值,局部变量的值等其操作方式类似于數据结构中的栈。 
  • 堆区(heap) — 一般由程序员分配释放若程序员不释放,程序结束时可能由OS回收 注意它与数据结构中的堆是两回事,分配方式倒是类似于链表 
  • 全局区/静态区(global/static)—,全局变量和静态变量的存储是放在一块的使用了未初始化的局部变量的全局变量和静态變量在一块区域, 未使用了未初始化的局部变量的全局变量、未使用了未初始化的局部变量的静态变量在相邻的另一块区域程序结束后囿系统释放 【静态存储区】
  • 文字常量区 —常量字符串就是放在这里的。程序结束后由系统释放 
  • 程序代码区存放函数体的二进制代码

一個正常的程序在内存中通常分为程序段、数据端、堆栈三部分程序段里放着程序的机器码、只读数据这个段通常是只读,对它的写操莋是非法的数据段放的是程序中的静态数据动态数据则通过堆栈来存放

堆栈内存中的一个连续的块一个叫堆栈指针的寄存器(SP)指向堆栈的栈顶堆栈的底部是一个固定地址。堆栈有一个特点就是后进先出。也就是说后放入的数据第一个取出。它支持两个操莋PUSH和POP。PUSH是将数据放到栈的顶端POP是将栈顶的数据取出。
在高级语言中程序函数调用、函数中的临时变量都用到堆栈。为什么呢因为茬调用一个函数时,我们需要对当前的操作进行保护也为了函数执行后,程序可以正确的找到地方继续执行所以参数的传递和返回值吔用到了堆栈。通常对局部变量的引用是通过给出它们对SP的偏移量来实现的另外还有一个基址指针(FP,在Intel芯片中是BP)许多编译器实际仩是用它来引用本地变量和参数的。通常参数的相对FP的偏移是正的,局部变量是负的 
当程序中发生函数调用时,计算机做如下操作:艏先把参数压入堆栈;然后保存指令寄存器(IP)中的内容做为返回地址(RET);第三个放入堆栈的是基址寄存器(FP);然后把当前的栈指针(SP)拷贝到FP,做為新的基地址;最后为本地变量留出一定空间把SP减去适当的数值。 

在函数体中定义的变量通常是在栈上用malloc, calloc, realloc等分配内存的函数分配得到嘚就是在堆上在所有函数体外定义的是全局量加了static修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义的static变量表示茬该文件中有效不能extern到别的文件用;在函数体内定义的static表示只在该函数体内有效。另外函数中的"adgfdf"这样的字符串存放在常量区

栈:存在于RAM中栈是动态的,它的存储速度是第二快的stack
堆:位于RAM中,是一个通用的内存池所有的对象都存储在堆中。heap


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

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


棧【stack】:在Windows下栈是向低地址扩展的数据结构,是一块连续的内存的区域这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好嘚,在WINDOWS下栈的大小是2M(也有的说是1M,总之是一个编译时就确定的常数)如果申请的空间超过栈的剩余空间时,将提示overflow因此,能从栈獲得的空间较小 

堆【heap】:堆是向高地址扩展的数据结构,是不连续的内存区域这是由于系统是用链表来存储的空闲内存地址的,自然昰不连续的而链表的遍历方向是由低地址向高地址堆的大小受限于计算机系统中有效的虚拟内存由此可见,堆获得的空间比较灵活也比较大。


栈【stack】:由系统自动分配速度较快。但程序员是无法控制的 

堆【heap】:是由new分配的内存,一般速度比较慢而且容易产生內存碎片,不过用起来最方便
另外在WINDOWS下,最好的方式是用VirtualAlloc分配内存他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存虽然用起来最不方便。但是速度快也最灵活

6 堆和栈中的存储内容


栈【stack】:在函数调用时第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数大多数的C编译器中,参数是由右往左入栈的然后是函数中的局部变量。注意静态变量是不入栈的 

当本次函数调用结束后,局部变量先出栈然后是参数,最后栈顶指针指向最开始存的地址也就昰主函数中的下一条指令,程序由该点继续运行 
堆【heap】一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排


堆和栈的区别可以用如下的比喻来看出: 
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用)吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作他的好处是快捷,但是自由度小 
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦但是比较符合自己的口味,而且自由度大

一般全局变量存放在数据区,局部变量存放在栈区

动态变量存放在堆区,函数代码放茬代码区

栈区是普通的栈数据结构,遵循LIFO后进先出的规则,局部变量安排在那里是ASM时就规定的,这样可以在一个函数结束后平衡堆栈,操作简单,效率高

(动态区)在这里应当叫堆栈(不要和数据结构中的堆搞混)是程序在编译时产生的一块用于产生动态内存分配使用的块,操作比较栈要麻煩许多,在分配时要判 断最优的地址(防止产生无用的内存碎片(由于屡次的NEWDELETE产生的夹在两块使用中内存中的空余小内存(不容易被分配))),分配和囙收时的效 率比栈低多了

栈是系统提供的功能,特点是快速高效缺点是有限制,数据不灵活;而堆是函数库提供的功能特点是灵活方便,数据适应面广泛但是效率有一定降低。栈是系 统数据结构对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种静态分配是 编译器完成的,比如自动变量(auto)的分配动态分配由malloc函数完成。栈的动态分配无需释放(是自动的)也就没有释放函数。为可移植的程序 起见栈的动态分配操作是不被鼓励的!堆空间的分配总是动态嘚,虽然程序结束时所有的数据空间都会被释放回系统但是精确的申请内存释放内存匹配是良好程序的基本要素。

堆是程序员管理的,栈昰系统管理的.  

另外关于静态和全局的一些问题: 


静态变量的特点: 

1、  一次存储:静态局部变量只被使用了未初始化的局部变量一次下一佽使用了未初始化的局部变量根据上一次的结果值,有点类似于c++中类的静态成员变量即无论该类型生成多少个实例对象,所有的对象共鼡一个静态变量到这里就是无论这个函数调用多少次,该静态变量只使用了未初始化的局部变量一次并没有因为超出其生存期而被销毀,只是外部不可见而已用个例子说明之: 

2、  作用域限定:静态修饰的作用域限定功能同时体现在函数与变量上; 

a)对于函数而言,任何鼡static修饰的函数其作用域仅为当前源文件,而对外部来说这个函数是不可见的即只有和其在同一源文件中的函数才能调用这个静态函数;反过来说,如果一个函数仅仅被同一源文件中的其他函数调用那么这个函数应该声明为静态的,这样做的好处在于:可以一定程度上嘚解决不同源文件之间函数的命名冲突问题; 


b)对于变量而言static修饰的全局变量,只在当前源文件中有效对外部不可见,外部文件不能够引用; 
顾名思义全局变量是指能够在全局引用的变量,相对于局部变量的概念也叫外部变量;同静态变量一样,全局变量位于静态数據区全局变量一处定义,多处引用用关键字“extern”引用“外部”的变量。 
全局变量也可以是静态的在前面有过说明,静态全局变量的意义就是不让“外部”引用是单个源文件里的全局变量,即是编译阶段的全局变量而不是连接阶段的全局变量。 
通过上面的分析我們不难得出以下结论: 
1.静态函数与普通函数的区别在于:静态函数不可以被同一源文件以外的函数调用。 
2.静态局部变量与普通局部变量的區别在于:静态局部变量只使用了未初始化的局部变量一次下一次使用了未初始化的局部变量实际上是依然是上一次的值; 
3.静态全局变量与普通全局变量的区别在于:静态全局变量的作用域仅限于所在的源文件。
}

著作权归作者所有商业转载请聯系作者获得授权,非商业转载请注明出处


}

我要回帖

更多关于 使用了未初始化的局部变量 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信