zoukankan      html  css  js  c++  java
  • C语言中堆内存的开辟和释放与内存处理函数

    C语言动态分配内存,malloc的出现就是来弥补静态内存分配的缺点

    比如说我们在定义数组的时候,数组的长度必须是一个常量,不能改变的值,假如我事先定义了数组,一旦业务需求发生改变,那么这个数组就不能再使用了。

    传统的数组定义也就是静态分配,是不能够手动释放的,只能等待系统释放,静态分配的内存,是分配在栈中的,C语言中的函数调用也是通过栈来实现的,栈有一个特点就是先进后出,在调用函数的时候,是先压入栈,然后从最上面的函数开始执行

    我们先来看看内存四区,分别为堆区,栈区,数据区,代码区,对于这四个区,做了以下总结

    代码区:
      程序执行二进制码(程序指令)
      共享,只读
    数据区 :
      初始化数据区(data)
      未初始化数据区(bss)
      常量区
    栈区 :
      系统为每一个程序分配一个临时的空间,
      局部变量,函数信息,函数参数,数组
      栈区大小为:1M
      在windows中可以扩展到10M
      在linux中可以扩展到16M
    堆区 :
      存储大数据,图片,音乐,视频
      手动开辟 malloc
      手动释放           free

    栈区大小为:1M,我们来验证一下

    int zhan[8200000] = { 0 };

    在C语言中,我们定义了一个数组,长度为820000,那么我们知道,在栈中我们最多可分配1M的内存,我们可以计算一下,这八百二十万的长度占了多大的内存,

    定义的是int类型,所以8200000*4=32800000(字节)

    得到的结果再除以1024,32800000/1024=32031.25(KB)

    得到的结果再除以1024,32031.25/1024=31.280517578125(M)

    大约是31M,最终运行起来,这个程序是会报错的。

    接下来我们就开辟堆内存存储数据,这就用到了函数malloc

    动态分配内存函数

                   malloc

    使用函数之前我们要引用头文件stdlib.h

    #include<stdlib.h>

     malloc函数语法示例

    int* p1 = (int*)malloc(sizeof(int))

    返回值类型为void* 类型,也就是指针类型,int* p1代表一个以int类型地址为内容的指针变量

    int类型在内存中占用的大小为 4字节。

    malloc括号中就是你要开辟的空间大小,单位是字节,分配一块连续的区域

    假如我要开辟一个空间,里面存储5个数字,那么代码如下

    int* p1 = (int*)malloc(sizeof(int)*5);

    这样的格式可以更容易的理解,当然你也可以像下面这么写

    int* p1 = (int*)malloc(20);

    如果地址开辟成功,返回一个内存地址,否则返回NULL,需要注意的是,如果开辟失败了,那么在后边的程序中调用,程序就会报错,所以有时候还要加一个判断条件,这点要注意

    if (p1 == NULL) {
            printf("程序异常");
            return -1;
        }

    成功以后,我们可以使用这个内存空间,对它进行赋值。

    在使用完之后,也可以调用free函数释放,代码如下

    free(p1);

    那么,当我们释放这个p1之后,这个内存空间还能调用吗?其实还可以调用的。在释放之后,这个内存地址就变成了一个野指针,还可以进行赋值

    为了避免野指针,在free(p1)后在加上一段代码

    p1 = NULL;

    赋值为NULL,这个是可有可无的。

    我们再来看一个函数,叫做内存操作函数

          memset(),memcpy(),memmove(),

    引用 string.h

    #include<string.h>

    1.memset()参数,  void *memset(void *s, intc, size_tn);

    我们来看看它的示例

    int* p = (int*)malloc(sizeof(int) * 10);
    memset(p, 0, 40);

    传入p这个内存地址,重置为0,字节为40字节

    它在重置为0时有效,并不是真正意义上的重置

    这个函数作用通常是一串连续的内存一起操作,不会单独对变量进行操作。

    2.memcpy(),参数,void *memcpy(void *dest, constvoid *src, size_tn);

    示例:

       int arr[] = { 1,2,3,4,5,6,7,8,9 };
        int* p = (int*)malloc(sizeof(int) * 9);
        memcpy(p, arr, sizeof(int) * 9);

    arr存在栈内存中,p存在堆内存中,我们现在要把arr中的数复制到p中,这就用到了  memcpy()函数

    用法:

            memcpy(新数据,源数据,内存大小(字节))

    它不同于strcpy()这个函数,strcpy()是字符串拷贝遇到会停止,而memcpy()拷贝的是内存,拷贝的内容和字节有关。

    如果参数1和参数2的内存地址重叠,可能会导致程序报错,应尽量避免

    3.memmove()

    memmove()功能用法和memcpy()一样,区别在于:dest和src所指的内存空间重叠时,memmove()仍然能处理,不过执行效率比memcpy()低些。

    4.memcmp(),参数,int memcmp(constvoid *s1, constvoid *s2, size_tn);

        int arr[] = { 1,2,3,4,5,6,7,8,9 };
        int arry[] = { 1,2,3,4,5 };
        int value = memcmp(arr, arry, 20);

    第一个参数和第二个参数进行比较,比较前20个字节,也就是前5个数,如果相等返回0,否则返回-1;

     同样可以比较字符串,代码如下:

        char arr[] = "hello word";
        char arry[] = "hello word";
        int value = memcmp(arr, arry, 11);
  • 相关阅读:
    数据库函数(备忘)
    C语言实现统计字符个数
    用链表做一个学生管理系统
    深入理解 JSON
    从 JDK 源码角度看 Object
    eclipse + maven搭建SSM框架
    Oracle12c版64位客户端安装步骤(32位安装步骤一样)
    Oracle12C版本安装步骤
    ArcGIS破解配置及oracle文件配置
    ArcGIS_Lisence安装步骤
  • 原文地址:https://www.cnblogs.com/NiuZiXiao/p/10233157.html
Copyright © 2011-2022 走看看