堆栈啥的
来源:互联网 发布:淘宝新店免费推广 编辑:程序博客网 时间:2024/05/21 11:16
C在内存空间的顺序是代码区,数据区,堆,栈
代码区:就是存放你的程序的编译后的可执行代码的地方了
数据区:存放你的程序静态数据,如全局变量、常量等。
栈:在函数调用中,保存程序的当前运行状态、函数的参数、返回结果等。
堆:在分配给一个程序的内存中,除了上面三部分,剩下的就是堆了,也就是程序的自由空间,局部变量(自动变量)等,还有New给指针用的空间,都在这里分配。
全局变量和静态变量存放于进程的数据段。 3. Windows下进程的栈空间会自动存到heap中,就是堆上,Obj *p = new Obj (); p的空间就是使用的堆
#include<stdio.h>
intmain()
{
char*p="abcdef"; //很多书上说:p在栈,“abcdef”在数据区 :没错!!!!
p[2]='W';
printf(p);
getchar();
return 0;
}
这个程序编译通过,但是问什么程序运行会出错? //p指向的是一块常量数据区,不能修改其值!!!!
另一个:
#include<stdio.h>
intmain()
{
chars[]="abcdef";//s在栈,“abcdef”在数据区 //正确!!!!!!!!!!
s[2]='W';
printf(s);
getchar();
return 0;
}
这个程序能够正常输出! //因为s是一个数组,分配的是一块栈上的内存,而上面只是一个指针,没申请内存!
下面的程序在第二行输出乱码:
#include<iostream>
usingnamespace std;
char *fun()
{
char p[]= "ABC";
return p;
}
voidmain()
{
char *s;
s =fun();
cout<< "Yang" << endl; //运行到此行停住,看看s的值是什么?"ABC"!
cout<< s << endl; //乱码了
}
若将 p[] 改为 *p 结果就正常了,这是为什么?
问老师的结果是 p[] 是在栈上分配,而 *p 是在堆上分配,可我并没有malloc或new啊?
问题一:
楼主似乎还没搞清楚存储类的一些细节。
char p[]是auto的,程序离开fun()后p[]就消失了,它本来的存储区域的内容是不确定的,所以s会出现乱码;而"ABC"是static的,此时s实际上是一个指向字符串常量的指针(只不过“ABC”仍然不能被其它函数直接链接),离开fen()后“ABC”仍存在,因此s能正确表示“ABC”的内容。
虽然char p[]和char *p同是局部变量,但对于char p[]来说,p是一个auto变量的地址,而非指向"ABC"(字符串常量)的地址,就是说,系统会为p[]分配不同于“ABC”所处区域的另一块内存,然后把“ABC”的内容复制过去,fen()结束后,p[]的内容不再确定,这会产生问题,会使s返回一个不确定的内容,因此系统会警告returning address of localvariable or temporary
。而对于char *p="ABC",系统把"ABC”的地址传给指针p,p的地址就是“ABC”字符串常量的地址,这个常量是static的,fen()结束后它仍存在,s指向的内容是确定的,因此系统不会给予警告。
在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。
char a[]= "a"; //数据保存在堆
char *b ="b"; //"b"保存在常量区,b保存在堆
intmain()
{
char c[]= "c"; //数据保存在栈上
char *d ="d"; //"d"保存在常量区,d保存在栈上
}
常量存储区是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。所以不能b[0],d[0]进行修改。将它们的地址输出:
printf("0x%08x0x%08x\n", &a, &(*a));
printf("0x%08x0x%08x\n", &b, &(*b));
printf("0x%08x0x%08x\n", &c, &(*c));
printf("0x%08x0x%08x\n", &d, &(*d));
在我的电脑上是:
0x080497740x08049774
0x080497780x080485f5
0xbfd917a90xbfd917a9
0xbfd917a40x080485e0
可以看到a,c是数组(&a==&(*a),&c==&(*c)),但b,d是指针,它们指向的区域基本是连续的(在常量区上),同时&a与&b,&c与&d的地址也是基本连续的。另外可以看到,对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
一般全局变量存放在数据区,局部变量存放在栈区,
动态变量存放在堆区,函数代码放在代码区。
---------------------------------------------------------------
栈区是普通的栈数据结构,遵循LIFO后进先出的规则,局部变量安排在那里是ASM时就规定的,这样可以在一个函数结束后平衡堆栈,操作简单,效率高
堆(动态区)在这里应当叫堆栈(不要和数据结构中的堆搞混)是程序在编译时产生的一块用于产生动态内存分配使用的块,操作比较栈要麻烦许多,在分配时要判断最优的地址(防止产生无用的内存碎片(由于屡次的NEW和DELETE产生的夹在两块使用中内存中的空余小内存(不容易被分配))),分配和回收时的效率比栈低多了
---------------------------------------------------------------
栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而堆是函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率 >有一定降低。栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存无法互相操作。栈空间分静态分配和动态分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的),也就没有释放函数。为可移植>的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/ 释放内存匹>配是良好程序的基本要素。
现在举个例子来说明这些“段”的区别
#include<malloc.h>
unsignedchar gvch;
unsignedchar short gvshort;
unsignedint gvint=0x12345645;
unsignedlong gvlong=0x87654321;
voidmain()
{
unsigned char array[10],*p;
p=malloc(10*sizeof(char));
while(1);
}
-----------------------------------------------------------------
以上程序中代码是存放在代码区中,比如while(1);
gvch与gvshort两个全局变量由于没有付初值所以存放在:bss段中
gvint与gvlong两个全局变量付初值了所以存放在:数据段中
array数组与p变量为局部变量所以存放在:栈区
malloc函数申请的空间是属于动态的,所以保存在:堆区
- 堆栈啥的
- 堆栈啥的2
- 数据结构的堆栈和内存的堆栈
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 任务0的内核堆栈,用户堆栈
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- 堆栈,堆栈,堆和栈的区别
- JavaScript中的new-prototype面向对象实现原理
- 多线程知识点-java
- iphone UI 开发教程
- C语言和设计模式(适配器模式) 【文章都是来自网络,只要自己吸取了就是自己的】
- 自定义ArrayAdapter初始化item项
- 堆栈啥的
- 十五.AutoCompleteTextView与DatePickerDialog的使用
- Android NDK安装及使用简介
- mysql相关数据的导出
- 111
- 一个SVN备份批处理脚本
- Android学习笔记(13)————利用SharedPreferences来保存应用程序的数据
- VBA调用Outlook2010 Ribbon上按钮的命令
- C语言和设计模式(策略模式) 【文章都是来自网络,只要自己吸取了就是自己的】