c语言变量最多声明几个,C语言变量声明内存分配

20180114154417444237.png

由c / C ++编译的程序所占用的内存分为以下几部分

1. 堆栈(stack)-程序在运行时由编译器自动分配,并存储函数的参数值和局部变量的值. 它的操作类似于数据结构中的堆栈. 程序结束时,编译器会自动释放它.

2. 堆(heap)-在内存中打开另一个存储区域. 通常,它是由程序员分配和释放的. 如果程序员不释放它,则操作系统可能会在程序结束时将其恢复. 请注意,它与数据结构中的堆有两个不同之处,分配方法类似于链表,呵呵.

3. 全局区域(静态区域)(静态)-编译器在编译时分配内存. 全局变量和静态变量的存储放在一起,初始化的全局变量和静态变量在一个区域中,而未初始化的全局变量和未初始化的静态变量在另一相邻区域中. -程序结束后由系统释放

4. 文字常量区域常数字符串放置在此处. 程序结束后由系统释放

5. 程序代码区-存储函数体的二进制代码.

示例程序

这是由一位资深的非常详细的人写的

[cpp]普通视图

// main.cppinta = 0;全局初始化区域char * p1;全局未初始化区域main(){intb; // stack chars [] =“ abc”; // stack char * p2; // stack char * p3 =“ 123456”; //“ 123456/0”在常量区域中,并且p3在堆栈中. staticintc = 0; //全局(静态)初始化区域p1 =(char *)malloc(10); p2 =(char *)malloc(20); // 10和20个字节的分配区域位于堆面积. strcpy(p1,“ 123456”); // 123456/0放置在常量区域中,编译器可以将其优化为p3指向“ 123456”的位置. }

===============

C语言程序的内存分配方法

1. 内存分配方法

共有三种分配内存的方式:

[1]从静态存储区分配. 编译程序时已经分配了内存,并且该内存在程序的整个运行过程中都存在. 例如,全局变量,静态变量.

[2]在堆栈上创建. 执行该函数时,可以在堆栈上创建该函数中局部变量的存储单元,并在函数执行结束时自动释放这些存储单元. 堆栈内存分配操作内置在处理器的指令集中,虽然效率很高,但是分配的内存容量有限.

[3]从堆分配,也称为动态内存分配. 程序运行时,请使用malloc或new申请任何数量的内存,程序员负责何时使用free或delete释放内存. 动态内存的生存时间由程序员确定,并且使用非常灵活,但是如果在堆上分配了空间,则有责任回收它,否则正在运行的程序将发生内存泄漏以及频繁的分配和释放. 不同大小的堆空间将在堆中生成碎片.

2. 程序的内存空间

c1a5e7b0fc0646caf4fef91dff136c2d.png

程序将操作系统分配给它的内存块分为四个区域,如下图所示.

由C / C ++编译的程序所占用的内存分为以下几部分,

1. 堆栈区-由编译器自动分配和释放,存储局部变量,函数参数,返回数据,返回地址等,这些分配给正在运行的函数. 其操作类似于数据结构中的堆栈.

2. 堆(heap)-通常由程序员分配和释放. 如果程序员不释放它,则操作系统可能会在程序结束时将其恢复. 分发方法类似于链表.

3. 全局区域(静态区域)(静态)-存储全局变量,静态数据和常量. 程序结束后,由系统释放.

4. 文字常量区域常数字符串放置在此处. 程序结束后,由系统释放.

5. 程序代码区-存储函数体的二进制代码(类成员函数和全局函数).

示例程序如下所示,

[cpp]普通视图

inta = 0; //全局初始化区域char * p1; //全局未初始化区域intmain(){intb; // Stack chars [] =“ abc”; // Stack char * p2; // Stack char * p3 =“ 123456”; // 123456在常量区域中,p3在堆栈中. staticintc = 0; //全局(静态)初始化区域p1 = newchar [10]; p2 = newchar [20]; //分配的区域和字节在堆区域中. strcpy(p1,“ 123456”); // 123456被放置在常量区域中,编译器可能会将其优化为p3指向“ 123456”的位置. }

3. 堆与栈比较

3.1申请方法

stack: 由系统自动分配. 例如,在函数中声明一个局部变量int b. 系统会自动在堆栈上为b创建空间.

堆: 程序员需要自己申请并指定大小. C中的malloc函数和C ++中的new运算符.

如果p1 =(char *)malloc(10); p1 =新字符[10];

如果p2 =(char *)malloc(10); p2 =新字符[20];

但是请注意,p1和p2本身在堆栈中.

3.2申请后的系统响应

080053208.png

堆栈: 只要堆栈的剩余空间大于请求的空间,系统就会为程序提供内存,否则它将报告异常并提示堆栈溢出.

堆: 首先,您应该知道操作系统有一个记录空闲内存地址的链表. 当系统从程序接收到一个应用程序时,它将遍历链接列表以查找第一个堆节点,该第一个堆节点的空间大于请求的空间,然后从可用节点列表中删除该节点,并删除该节点的空间分配给程序.

对于大多数系统,此分配的大小将记录在此内存空间的第一个地址上,以便代码中的delete语句可以正确释放此内存空间.

由于找到的堆节点的大小不一定等于应用程序的大小,因此系统会自动将多余的部分放入空闲列表中.

3.3应用程序大小的限制

堆栈: 在Windows下,堆栈是一种数据结构,可扩展到低位地址,并且是连续的内存区域. 这句话意味着系统要确定堆栈顶部的地址和堆栈的最大容量. 在WINDOWS下,堆栈的大小为2M(简而言之,为1M,这是在编译时确定的常数),如果当请求的空间超过堆栈上的剩余空间时,将提示溢出. 因此,堆栈中的可用空间很小.

堆: 堆是一种数据结构,可以扩展到更高的地址,并且是不连续的内存区域. 这是因为系统使用链接列表存储自然不连续的空闲内存地址,并且链接列表的遍历方向是从低地址到高地址. 堆的大小受计算机系统中可用的虚拟内存限制. 这表明堆获得的空间更加灵活,更大.

3.4应用效率比较

系统自动分配堆栈,速度更快. 但是程序员无法控制.

堆是new分配的内存,通常较慢并且更容易出现内存碎片,但是使用起来最方便.

此外,在WINDOWS下,最好的方法是使用VirtualAlloc分配内存. 他不在堆或堆栈上,而是直接在进程的地址空间中保留快速内存,尽管使用起来最不方便. 但这是快速而灵活的.

3.5在堆和堆栈中存储内容

堆栈: 调用一个函数时,要压入堆栈的第一个是主函数中下一条指令的地址(该函数调用语句的下一个可执行语句),然后是该函数的各个参数. 功能. 在C编译器中,参数从右到左堆叠,然后在函数中堆叠局部变量. 请注意,静态变量不会被压入堆栈.

此函数调用结束时,首先将局部变量弹出堆栈,然后是参数,最后堆栈上的顶部指针指向其最初存储的地址,这是主函数中的下一条指令,该程序将从那时开始继续运行.

堆: 通常,一个字节用于在堆的开头存储堆的大小. 堆中的特定内容由程序员安排.

3.6访问效率比较

char s1 [] =“ a”;

char * s2 =“ b”;

23220836-4fce9f32fcbad4826e484ff6f3c9c3.jpg

a在运行时分配; b是在编译时确定的;但是,在将来的访问中,堆栈上的数组比指针所指向的字符串(例如堆)要快. 例如:

[cpp]普通视图

intmain(){chara = 1; charc [] =“ 1234567890”; char * p =“ 1234567890”; a = c [1]; a = p [1]; return0;}

相应的汇编代码

10: a = c [1];

00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]

0040106A 88 4D FC mov字节ptr [ebp-4],cl

11: a = p [1];

0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]

00401070 8A 42 01 mov,byte ptr [edx + 1]

00401073 88 45 FC mov字节ptr [ebp-4],al

第一种在读取时将字符串中的元素直接读取到寄存器cl中,第二种首先将指针值读取到edx中,然后根据edx读取字符,这显然很慢.

3.7摘要

堆和栈之间的主要区别如下:

1. 不同的管理方式;

2. 空间的大小不同;

3. 是否可以产生碎片是不同的;

4. 不同的生长方向;

20200602114830420224.png

5. 不同的分配方式;

6. 不同的分配效率;

管理方法: 对于堆栈,它是由编译器自动管理的,无需我们手动控制;对于堆,释放工作由程序员控制,很容易产生内存泄漏.

空间大小: 通常,在32位系统中,堆内存可以达到4G. 从这个角度来看,堆内存几乎没有限制. 但是对于堆栈,通常会有一定的空间,例如,在VC6下,默认堆栈空间大小为1M. 当然,可以修改此值.

碎片: 对于堆,频繁的new / delete不可避免地会导致内存空间的不连续,从而导致大量的碎片,从而降低程序效率. 对于堆栈而言,这个问题不存在,因为堆栈是首先出现的队列c语言内存分配对应,它们之间是的对应关系,因此在弹出之前,永远不会有从堆栈中间弹出的内存块,他上方向后堆叠的内容已弹出. 有关详细信息,请参阅数据结构.

增长方向: 对于堆来说,增长方向是向上的,即内存地址增加的方向;对于堆栈,其增长方向是向下的,朝着内存地址减少的方向增加.

分配方法: 堆是动态分配的,没有静态分配的堆. 堆栈有2种分配方法: 静态分配和动态分配. 静态分配是由编译器完成的,例如局部变量的分配. 动态分配是通过Malloca函数分配的,但是堆栈和堆的动态分配是不同的. 他的动态分配是由编译器释放的,而无需我们手动执行.

分配效率: 堆栈是机器系统提供的数据结构. 计算机将在底部支持堆栈: 分配特殊的寄存器来存储堆栈地址,并通过推入和弹出堆栈执行特殊指令来确定堆栈. 效率比较高. 堆由C / C ++函数库提供. 其机制非常复杂. 例如,为了分配一块内存,库函数将根据某种算法(特定算法可以引用数据结构/操作系统)在堆内存中搜索可用内存. 如果没有足够的空间(可能是由于内存碎片过多),则可以调用系统函数来增加程序数据段的内存空间,以便您有机会分配足够的内存,然后继续返回. 显然,堆的效率要比堆的效率低得多.

从这里我们可以看到,与堆和栈相比,由于使用了大量的new / delete,很容易造成很多内存碎片;因为没有特殊的系统支持c语言内存分配对应,所以效率很低;因为可能会导致用户模式和核心模式的切换,内存应用的成本变得更加昂贵. 因此,堆栈是程序中使用最广泛的堆栈,即使也使用堆栈完成了函数调用,函数调用过程中的参数,返回地址,EBP和局部变量也存储在堆栈中. 因此,我们建议您尝试使用堆栈而不是堆.

尽管堆栈有很多好处,因为与堆相比,它不那么灵活,但有时最好使用堆来分配大量内存空间.

无论是堆还是堆栈,都必须防止发生越界(除非您有意使越界),因为越界的结果就是程序崩溃,或者程序的堆和堆栈结构被破坏,从而产生意外结果.

4. new / delete和malloc / free的比较

从C ++的角度来看,使用new分配堆空间可以调用该类的构造函数,而malloc()函数只是一个函数调用. 它不调用构造函数. 它接受的参数是无符号的long类型. 同样,delete会在释放堆空间之前调用析构函数,但free函数不会.

[cpp]普通视图

classTime {public: Time(int,int,int,string);〜Time(){cout <

结果:

致电时间的构造函数为: t2

通话时间的析构函数是: t2

从结果可以看出,使用new / delete可以调用对象的构造函数和析构函数,而该示例调用非默认构造函数. 但是,当在堆上分配对象数组时,只能调用默认构造函数,而不能调用其他构造函数.

Go: ; do = blog&id = 7605

本文来自电脑杂谈,转载请注明本文网址:

http://www.pc-fly.com/a/jisuanjixue/article-266193-1.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值