c语言基础(五)之内存、堆栈区

简介:

 

 

指针运算:

指针的运算在数组的运算中才有意义。其它指针操作的运算都无意义。

 

只要是指针类型,它在内存中所占的长度都是4个byte。(前提是32位系统)

 

传统数组被创建出来,它是被创建在栈空间上的。也就是说程序员没有办法

去清空栈空间上的内容。

 

动态内存分配:

使用malloc函数,能够动态分配内存。注意要引入#include<malloc.h>函数头文件

malloc(a);a表示int类型参数。就是要申请多少个byte长度的内存。

       返回值 :是申请县的空间的首地址(void类型)。它是一个指针类型的返回值。

                      要作相应的强制类型转换。

释放空间free(p);//p首地址

记住:在free后尽量不要在使用该变量。

       避免错误方法:在释放free(p)后,p=NULL(大写);若其它地方有使用p,则会有错误提示。

 

用动态分配内存,可以在主函数中使用子函数的变量的值。

 

例子:

int len=0;

scanf("%d",&len);

int* p = (int*)malloc(sizeof(int)*len)//若len=6,执行完毕后,申请了多少byte内存?

 //1.静态申请的内存 int* 4byte

 //2.动态内存4*6=24byte

 //所以,总共申请了 24+4 = 28byte内存

 

realloc(p,q);//p表示:重新分配哪一块内存空间,q表示:重新分配的大小

           返回值:是内存空间的首地址。

 

静态内存和动态内存:

静态内存是程序编译执行后系统自动分配的,由系统自动释放。静态内存

                 是栈分配的。动态内存是堆分配的。

 

静态内存和动态内存区别:

1.从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在

    程序的整个运行期间都存在。例如:全局变量,static变量

2.在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,

    函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的

    指令集中,效率很高,但是分配的内存容量有限。

3.从堆上分配,亦称动态内存分配。程序在运行的时候用mallo(c)c或new(java)申请任意

   多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存

   期由我们决定,使用非常灵活,但问题也最多。

 

堆和栈的区别:

1.申请方式:

栈:由系统自动分配,例如,声明一个局部变量int b;系统自动在栈中为b开辟空间,

        栈空间是后进先出,由系统释放空间。

堆:需要程序员自己申请,并指明大小,在c中用malloc函数

        如:p1=(char*)malloc(10);

              但是注意p1本身是在栈中的。

2.申请后系统的响应

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

堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,

       会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点

       链表中删除,并将该结点的空间分配给程序,另外,对于大多数系统,会在这块内存

       空间中的首地址处记录本次分配的大小,这样,代码中的delete语句才能正确的释放

       本内存空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动

       的将多余的那部分重新放入空闲链表中。

3.申请大小的限制

栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的

        意思是栈顶的地址和栈的最大容量是系统预先规定好的,在windows下,栈的大小是

        2M(vc编译选项中可以设置,其实就是一个stack参数,缺省值2M),如果申请的空间

        超过酷我剩余空间时,将提示overflow。因此,能从栈获得的空间比较小。

堆:是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲

        内存地址的,自然是不连续的。而链表的遍历方向是由低向高地址。堆的大小受限于计算机

        系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。

4.申请效率的比较:

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

堆:由malloc/new分配的内存,一般速度 比较慢,而且容易产生内存碎片,不过用起来方便。

5堆和栈的存储内容:

栈:在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行

       语句 )的地址,然后是函数的各个参数,在大多数的c编译器中,参数是由右往左入栈的,

      然后是函数中的局部变量。注意:静态变量是不入栈的。

堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。

6.内存的回收

栈:栈上的分配的内存,编译器会自动回收。

堆:堆上分配的内存,要通过free来显示的收回,否则会造成内存泄漏。

 

                               

 

 

目录
相关文章
|
1月前
|
存储 编译器 程序员
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
在C语言中,内存布局是程序运行时非常重要的概念。内存布局直接影响程序的性能、稳定性和安全性。理解C程序的内存布局,有助于编写更高效和可靠的代码。本文将详细介绍C程序的内存布局,包括代码段、数据段、堆、栈等部分,并提供相关的示例和应用。
51 5
【C语言】内存布局大揭秘 ! -《堆、栈和你从未听说过的内存角落》
|
1月前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
67 6
|
2月前
|
传感器 人工智能 物联网
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发
C 语言在计算机科学中尤其在硬件交互方面占据重要地位。本文探讨了 C 语言与硬件交互的主要方法,包括直接访问硬件寄存器、中断处理、I/O 端口操作、内存映射 I/O 和设备驱动程序开发,以及面临的挑战和未来趋势,旨在帮助读者深入了解并掌握这些关键技术。
57 6
|
2月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
169 13
|
2月前
|
大数据 C语言
C 语言动态内存分配 —— 灵活掌控内存资源
C语言动态内存分配使程序在运行时灵活管理内存资源,通过malloc、calloc、realloc和free等函数实现内存的申请与释放,提高内存使用效率,适应不同应用场景需求。
|
2月前
|
存储 算法 程序员
C 语言指针详解 —— 内存操控的魔法棒
《C 语言指针详解》深入浅出地讲解了指针的概念、使用方法及其在内存操作中的重要作用,被誉为程序员手中的“内存操控魔法棒”。本书适合C语言初学者及希望深化理解指针机制的开发者阅读。
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
67 1
|
2月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
2月前
|
缓存 Prometheus 监控
Elasticsearch集群JVM调优设置合适的堆内存大小
Elasticsearch集群JVM调优设置合适的堆内存大小
394 1
|
1月前
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。