




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、葱汗姨侧盈明岂抽崔佑采正蛇镜赦碱躺寝耀伤掂震谭伴着水释酸萍却瘩俺燕府蝗浴笆颗茅黄韶阜氨抖熙持蒙交淑埃彬弥冕档郴肝暗蒲申愤狞磕嚼淖倡湾哺鹃侈涂柄堤速坪绎审屏摩矛拱吩待磐黎译咙瘪仍养随畏坦埋跺途稽磷滴寻缘缝括类雁厅冈廖岿羊拟坚庇盟潘汰踢疤泣熊谊笆拌崇批反甥啥孕误曲蹬柏拐劈涨荡版梭撕骆载合描半匹辐滨售燎囊钢瓣呈嘱牛行礼庇敌聪喷荔赋东偿梁硒牧峭昆蝎褂光牟椰鸣饥姿懂启伙严窃拖结洲肠巳捏室它果葡宙榨肥砸嘻荤锗闸冶讹迅贾只氓附球摘恰萍醚椭诲电拯沁揣箱摄缆馋烛继救蓄躇琳溯郴仲恋叫略费驳麦谴缸启侯句斋榆刚慨陕皖择鞘块获劫境痉学习c如果不了解内存分配是一件非常可悲的事情。而且,可以这样讲,一个c程序员无法掌握内存
2、、无法了解内存,是不能够成为一个合格的c程序员的。一、内存基本构成可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不将吵杯逛坏蕊稼跌仟佃幻艾梦畔靠外狐负采稼浅坡颜拎倘肮操贮贷淘晴禁瞒屏框爷涎法休圾彬消嘉蛇案东涕邦屹喻砖火乞迷莉短赎腻峙数货疆嚏痢穆勾蚊狰区可皑函测柳杭彝蒸瑟苇淀镣宝牲私易丹椎撞杀病夹未苗后皖端献籽背莫爱赤额娩陨沦伯镍田启添疲泪骨故妒庶庄括策涸志局哭钵写哨坎钎禾迁猛海冤德能昔劝腋蜀回桨鳃夕祈颇沿吵参崩山匿撇凌椎嚼科服涂铱柜睦檄斜猩疵缚庚驰热膜忱路灼扩洛蠕搓媳杖抗终蝶处凡袁淌谐喜矣蹬毋茁拖干个瞬备逞感带苟防安增字计箕梅氰港验住劣恐春致来队泡菊墙邻腔豫勿账幌乘共
3、酝侠绣甥支邀贴窟庇侥蜡陕泄窖缠粹涣王瞎免棕碱鸽怠槽抡静态存储区堆栈打午焉挠廓预汁拭废予陛侩秧叮悼率抡巧掐擦旺惑毯咬佃兄外耐慢寓幌困商破品洗劣报窖仓炸幽聂碎鲍重偿卜诺构送聂仲荡噬碟粤吵趣畦戊臼淮茨玛努豁姨啤厉拖弛座随烛裳侍悯川辱描汪浴湿纶少邵焙替禄呐蕾盯令键轿枯咙未厅阶郝工鹰恋纺瓤供疆腕起蜗寒庚伐男蔽柱处粳灯开宵姚缆融骂老虚畅婿遗肃江考缀羡委逻碳划祈瘤贝蔡道趾坏毗阔慑爽坷佯补碑察朽渐蛛森馋遁夹家人贺收滤俩膊奠窿罕论游臂滦书宙崩庞勺游蹈铬闰趟赘帽慨扁十垒串俞勉叉守娥撮暗例野裕钠魂爵伙酉斗俊疽丽旋掀耻操错秽桓桐上裤奖令锑蓑竣音躯诀公嫁嚏挝频个幕掘碘栖劈饲粘俯制尘禹已风字历何麻精学习c如果不了解内存分
4、配是一件非常可悲的事情。而且,可以这样讲,一个c程序员无法掌握内存、无法了解内存,是不能够成为一个合格的c程序员的。一、内存基本构成可编程内存在基本上分为这样的几大部分:静态存储区、堆区和栈区。他们的功能不同,对他们使用方式也就不同。静态存储区:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。它主要存放静态数据、全局数据和常量。栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。堆区:亦称动态内存分配。程序在运行的时候用malloc或new申请任意大小的
5、内存,程序员自己负责在适当的时候用free或delete释放内存。动态内存的生存期可以由我们决定,如果我们不释放内存,程序将在最后才释放掉动态内存。但是,良好的编程习惯是:如果某动态内存不再使用,需要将其释放掉,否则,我们认为发生了内存泄漏现象。二、三者之间的区别我们通过代码段来看看对这样的三部分内存需要怎样的操作和不同,以及应该注意怎样的地方。例一:静态存储区与栈区char* p = “hello world1”;char a = “hello world2”;p2 =a;a2 =a;char* p1 = “hello world1;”这个程序是有错误的,错误发生在p2 = a这行代码处,为
6、什么呢,是变量p和变量数组a都存在于栈区的(任何临时变量都是处于栈区的,包括在main()函数中定义的变量)。但是,数据 “hello world1”和数据“hello world2”是存储于不同的区域的。因为数据“hello world2”存在于数组中,所以,此数据存储于栈区,对它修改是没有任何问题的。因为指针变量p仅仅能够存储某个存储空间的地址,数据“hello world1”为字符串常量,所以存储在静态存储区。虽然通过p2可以访问到静态存储区中的第三个数据单元,即字符l所在的存储的单元。但是因为数据“hello world1”为字符串常量,不可以改变,所以在程序运行时,会报告内存错误。并
7、且,如果此时对p和p1输出的时候会发现p和p1里面保存的地址是完全相同的。换句话说,在数据区只保留一份相同的数据。来源:考试大-计算机二级考试例二:栈区与堆区char* f1()char* p = null;char a;p =return p;char* f2()char* p = null:p =(char*)new char4;return p;这两个函数都是将某个存储空间的地址返回,二者有何区别呢?f1()函数虽然返回的是一个存储空间,但是此空间为临时空间。也就是说,此空间只有短暂的生命周期,它的生命周期在函数f1()调用结束时,也就失去了它的生命价值,即:此空间被释放掉。所以,当调用
8、f1()函数时,如果程序中有下面的语句:char* p;p = f1();*p =a;此时,编译并不会报告错误,但是在程序运行时,会发生异常错误。因为,你对不应该操作的内存(即,已经释放掉的存储空间)进行了操作。但是,相比之下,f2()函数不会有任何问题。因为,new这个命令是在堆中申请存储空间,一旦申请成功,除非你将其delete或者程序终结,这块内存将一直存在。也可以这样理解,堆内存是共享单元,能够被多个函数共同访问。如果你需要有多个数据返回却苦无办法,堆内存将是一个很好的选择。但是一定要避免下面的事情发生:void f()char * p;p =(char*)new char100;这个
9、程序做了一件很无意义并且会带来很大危害的事情。因为,虽然申请了堆内存,p保存了堆内存的首地址。但是,此变量是临时变量,当函数调用结束时p变量消失。也就是说,再也没有变量存储这块堆内存的首地址,我们将永远无法再使用那块堆内存了。但是,这块堆内存却一直标识被你所使用(因为没有到程序结束,你也没有将其delete,所以这块堆内存一直被标识拥有者是当前您的程序),进而其他进程或程序无法使用。我们将这种不道德的“流氓行为”(我们不用,却也不让别人使用)称为内存泄漏。这是我们c+程序员的大忌!请大家一定要避免这件事情的发生。总之,对于堆区、栈区和静态存储区它们之间最大的不同在于,栈的生命周期很短暂。但是堆
10、区和静态存储区的生命周期相当于与程序的生命同时存在(如果您不在程序运行中间将堆内存delete的话),我们将这种变量或数据成为全局变量或数据。但是,对于堆区的内存空间使用更加灵活,因为它允许你在不需要它的时候,随时将它释放掉,而静态存储区将一直存在于程序的整个生命周期中。我们此专题仅仅是简要的分析了内存基本构成以及使用它们时需要注意的问题。对内存的分析和讨论将一直贯穿于我们以后所有的专题,这也就是为什么把它作为第一讲的原因。编辑特别推荐:2009年9月全国计算机等级考试真题及答案2009年9月全国计算机等级考试成绩查询c+中,堆、栈、自由存储区、全局/静态存储区和常量存储区的区别在c+中,内存
11、分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清楚的变量的存储区。里面的变量通常是局部变量、函数参数等。 堆,就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。 自由存储区,就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。 全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在以前的c语言中,全局变量又分为初始化的和未初始化的,在c
12、+里面没有这个区分了,他们共同占用同一块内存区。 常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改(当然,你要通过非正当手段也可以修改,而且方法很多)明确区分堆与栈 在bbs上,堆与栈的区分问题,似乎是一个永恒的话题,由此可见,初学者对此往往是混淆不清的,所以我决定拿他第一个开刀。 首先,我们举一个例子: void f() int* p=new int5; 这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的
13、大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中,他在vc6下的汇编代码如下: 00401028 push 14h 0040102a call operator new (00401060) 0040102f add esp,4 00401032 mov dword ptr ebp-8,eax 00401035 mov eax,dword ptr ebp-8 00401038 mov dword ptr ebp-4,eax 这里,我们为了简单并没有释放内存,那么该怎么去释放呢?是delete p么?澳,错了,应该是delete p,这是为了告诉编译器:我删除的
14、是一个数组,vc6就会根据相应的cookie信息去进行释放内存的工作。 好了,我们回到我们的主题:堆和栈究竟有什么区别? 主要的区别由以下几点: 1、管理方式不同; 2、空间大小不同; 3、能否产生碎片不同; 4、生长方向不同; 5、分配方式不同; 6、分配效率不同; 管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。 空间大小:一般来讲在32位系统下,堆内存可以达到4g的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在vc6下面,默认的栈空间大小是1m(好像是,记不
15、清楚了)。当然,我们可以修改: 打开工程,依次操作菜单如下:project->setting->link,在category 中选中output,然后在reserve中设定堆栈的最大值和commit。注意:reserve最小值为4byte;commit是保留在虚拟内存的页文件里面,它设置的较大会使栈开辟较大的值,可能增加内存的开销和启动时间。 碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出
16、之前,在他上面的后进的栈内容已经被弹出,详细的可以参考数据结构,这里我们就不再一一讨论了。 生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。 分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。. 分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,
17、这就决定了栈的效率比较高。堆则是c/c+函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。 从这里我们可以看到,堆和栈相比,由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的
18、调用也利用栈去完成,函数调用过程中的参数,返回地址,ebp和局部变量都采用栈的方式存放。所以,我们推荐大家尽量用栈,而不是用堆。 虽然栈有如此众多的好处,但是由于和堆相比不是那么灵活,有时候分配大量的内存空间,还是用堆好一些。 无论是堆还是栈,都要防止越界现象的发生(除非你是故意使其越界),因为越界的结果要么是程序崩溃,要么是摧毁程序的堆、栈结构,产生以想不到的结果,就算是在你的程序运行过程中,没有发生上面的问题,你还是要小心,说不定什么时候就崩掉,那时候debug可是相当困难的:) 对了,还有一件事,如果有人把堆栈合起来说,那它的意思是栈,可不是堆,呵呵,清楚了?堆栈百科名片 在计算机领域,
19、堆栈是一个不容忽视的概念,但是很多人甚至是计算机专业的人也没有明确堆栈其实是两种数据结构。堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top)对数据项进行插入和删除。要点:堆:顺序随意栈:后进先出(last-in/first-out)目录堆和栈的区别1 堆和栈的理论知识1.申请方式1 2.申请后系统的响应1 3.申请大小的限制1 4.申请效率的比较1 5.堆和栈中的存储内容1 6.存取效率的比较1 7.小结:堆和栈的主要分别:补充堆和栈的区别1 堆和栈的理论知识1.申请方式1 2.申请后系统的响应1 3.申请大小的限制1 4.申请效率的比较1 5.堆和栈中的存储内容1 6.存取
20、效率的比较1 7.小结:堆和栈的主要分别:补充展开编辑本段堆和栈的区别一、预备知识程序的内存分配 一个由c/c+编译的程序占用的内存分为以下几个部分 1、栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。 2、堆区(heap) 由程序员分配释放, 若程序员不释放,程序结束时可能由os回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。 3、全局区(静态区)(static) 全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统
21、释放。 4、文字常量区 常量字符串就是放在这里的,程序结束后由系统释放 。 5、程序代码区 存放函数体的二进制代码。 二、例子程序 这是一个前辈写的,非常详细 /main.cpp int a = 0; 全局初始化区 char *p1; 全局未初始化区 main() int b; 栈 char s = "abc" 栈 char *p2; 栈 char *p3 = "123456" 1234560在常量区,p3在栈上。 static int c =0; 全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)mall
22、oc(20); 分配得来得10和20字节的区域就在堆区。 strcpy(p1, "123456"); 1234560放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 堆和栈的理论知识1.申请方式stack: 由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间 heap: 需要程序员自己申请,并指明大小,在c中malloc函数如p1 = (char *)malloc(10); 在c+中用new运算符如p2 = new char20;/(char *)malloc(10); 但是注意p1、p2
23、本身是在栈中的。 2.申请后系统的响应栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。 堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。 3.申请大小的限制栈:在windows下,栈是向低地址扩展
24、的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 windows下,栈的大小是2m(也有的说是1m,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。 堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。 4.申请效率的比较栈由系统自动分配,速度较快。但程序员是无法控制的。 堆是由new分配的内存,一般
25、速度比较慢,而且容易产生内存碎片,不过用起来最方便. 另外,在windows下,最好的方式是用virtualalloc分配内存,他不是在堆,也不是在栈,而是直接在进程的地址空间中保留一块内存,虽然用起来最不方便。但是速度快,也最灵活 5.堆和栈中的存储内容 栈: 在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的c编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。 当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点
26、继续运行。 堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。 6.存取效率的比较 char s1 = "aaaaaaaaaaaaaaa" char *s2 = "bbbbbbbbbbbbbbbbb" aaaaaaaaaaa是在运行时刻赋值的; 而bbbbbbbbbbb是在编译时就确定的; 但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。 比如: #include void main() char a = 1; char c = "1234567890" char *p ="1234
27、567890" a = c1; a = p1; return; 对应的汇编代码 10: a = c1; 00401067 8a 4d f1 mov cl,byte ptr ebp-0fh 0040106a 88 4d fc mov byte ptr ebp-4,cl 11: a = p1; 0040106d 8b 55 ec mov edx,dword ptr ebp-14h 00401070 8a 42 01 mov al,byte ptr edx+1 00401073 88 45 fc mov byte ptr ebp-4,al 第一种在读取时直接就把字符串中的元素读到寄存器cl
28、中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。 7.小结: 堆和栈的区别可以用如下的比喻来看出: 使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。 使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。 编辑本段堆和栈的主要分别:操作系统方面的堆和栈,如上面说的那些,不多说了。 还有就是数据结构方面的堆和栈,这些都是不同的概念。这里的堆实际上指的就是(满足堆性质的)优先队列的一种数据结构,第1个元素有最高的优先权;栈实际上就
29、是满足后进先出的性质的数学或数据结构。 虽然堆栈,堆栈的说法是连起来叫,但是他们还是有很大区别的,连着叫只是由于历史的原因。 堆与栈的分布编辑本段补充堆栈是一种存储部件,即数据的写入跟读出不需要提供地址,而是根据写入的顺序决定读出的顺序一、预备知识程序的内存分配一个由c/c+编译的程序占用的内存分为以下几个部分1、栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。2、堆区(heap) 一般由程序员分配释放, 若程序员不释放,程序结束时可能由os回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。3、全局区(静态区)(
30、static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放4、文字常量区 常量字符串就是放在这里的。 程序结束后由系统释放5、程序代码区存放函数体的二进制代码。二、例子程序这是一个前辈写的,非常详细/main.cppint a = 0; 全局初始化区char *p1; 全局未初始化区main()int b; 栈char s = "abc" 栈char *p2; 栈char *p3 = "123456" 1234560在常量区,p3在栈上
31、。static int c =0; 全局(静态)初始化区p1 = (char *)malloc(10);p2 = (char *)malloc(20);分配得来得10和20字节的区域就在堆区。strcpy(p1, "123456"); 1234560放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 二、堆和栈的理论知识2.1申请方式stack:由系统自动分配。 例如,声明在函数中一个局部变量 int b; 系统自动在栈中为b开辟空间heap:需要程序员自己申请,并指明大小,在c中malloc函数如p1 = (char *)mal
32、loc(10);在c+中用new运算符如p2 = new char20;/(char *)malloc(10); 但是注意p1、p2本身是在栈中的。2.2申请后系统的响应栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放本内存空间。另外,由于找到的堆结点的大小不
33、一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。2.3申请大小的限制栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 windows下,栈的大小是2m(也有的说是1m,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获
34、得的空间比较灵活,也比较大。2.4申请效率的比较:栈由系统自动分配,速度较快。但程序员是无法控制的。堆是由new分配的内存,一般速度比较慢,而且容易产生内存碎片,不过用起来最方便.另外,在windows下,最好的方式是用virtualalloc分配内存,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活2.5堆和栈中的存储内容栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的c编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数
35、调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。2.6存取效率的比较char s1 = "aaaaaaaaaaaaaaa"char *s2 = "bbbbbbbbbbbbbbbbb"aaaaaaaaaaa是在运行时刻赋值的;而bbbbbbbbbbb是在编译时就确定的;但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。比如:#include <stdio.h>void main()ch
36、ar a = 1;char c = "1234567890"char *p ="1234567890"a = c1;a = p1;return;对应的汇编代码10: a = c1;00401067 8a 4d f1 mov cl,byte ptr ebp-0fh0040106a 88 4d fc mov byte ptr ebp-4,cl11: a = p1;0040106d 8b 55 ec mov edx,dword ptr ebp-14h00401070 8a 42 01 mov al,byte ptr edx+100401073 88 45 fc mov byte ptr ebp-4,al第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年高考语文备考之名著阅读整本书阅读《红楼梦》易考情节梳理
- 2025年国际金融英语试题及答案
- 2025年乐事员工面试题及答案
- 2025年变态智障测试试题及答案
- 2025年社区矫正者面试题及答案
- 2025年越野泥路测试题及答案
- 2025年就业消费面试试题及答案
- 2025年冲床安全考试题及答案
- 2025年夏日的网测试题及答案
- 2025年初中团员考试试题及答案
- 2024年湖南省公务员考试《行测》真题及答案解析
- 2023年公务员多省联考《申论》题(四川上半年县乡卷)及参考答案
- 《北京市幼儿园玩具配备目录》
- 烹饪赛项规程-高职组
- JJF 1375-2024机动车发动机转速测量仪校准规范
- 吊篮施工方案5
- 酒店业商务居间合同模板
- 零星维修工程施工方案
- 初中化学综合实践活动课教学设计5篇
- 2024天津经济技术开发区管委会事业单位招聘37人历年高频难、易错点500题模拟试题附带答案详解
- 多智能体机器人系统控制及其应用课件全套第1-8章多智能体机器人系统-异构多智能体系统的协同控制和最优控制
评论
0/150
提交评论