动态内存分配

1.为什么使用动态内存分配


 答:为解决未知长度数组的相关问题


2.malloc 和 free

void *malloc(size_t size); //分配动态内存

void free(void *pointer);  //释放动态内存

 malloc:参数 size:需要分配的内存字节数

                 若成功,返回一个指向被分配的内存块(分配的是一个连续的内存,且未初始化)起始位置的指针

                  若失败,返回 NULL 指针

free: 参数要么是 NULL(无任何效果),要么是 malloc,calloc 或 realloc 返回的值。


3.calloc 和 realloc


void *calloc(size_t num_elements, size_t element_size);

void *realloc(void *ptr, size_t new_size);

calloc:也用于分配内存,与 malloc 的区别是其在返回指向内存的指针之前它初始化为0

              参数: num_elements:元素数量, element_size:每个元素的字节数

realloc:用于修改一个原先已经分配的内存块的大小

                扩大:原内容保留,新增内容放到原内存后面,并且未初始化

                缩小:内存块尾去除,剩余 部分保留

                若无法改变内存块大小,分配另一块正确大小的新内存,复制原内存到此内存块上。因此,在使用 realloc

之后,不能再使用旧内存指针,而应改用返回的新指针。

                如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。

                若第一个参数为 NULL,则与 malloc等效


4.使用动态内存分配

int *pi;
...
pi = malloc(100);
if (pi == NULL)
{
    printf("Out of memory!\n");
    exit(1);
}

如果分配成功,这块内存被当作25个整型元素的数组(设整形为4个字节),因为 pi 是一个指向整型的指针

如果目标就是获得足够存储25个整数的内存,有更好的可移植的技巧:

pi = malloc(25 * sizeof(int));

如何使用这块内存:可以使用间接访问和指针运算来访问数组的不同整数位置,和一般指针使用相同。


5.常见动态内存错误


错误包括对 NULL 指针进行解引用操作,对分配的内存进行操作时越过边界,释放并非动态分配的内存,试图释放一块动态分配的内存的一部分

以及一块动态内存被释放之后被继续使用。


内存泄漏:分配内存但在使用完毕后不释放将引起内存泄漏


6.内存分配实例

a. 读取一列数据,并按升序排列他们并打印

#include<stdlib.h>
#include<stdio.h>

int compare_integers(void const *a, void const *b)//指定排序的顺序函数
{
    register int const *pa = a;
    register int const *pb = b;

    return *pa > *pb ? 1 : *pa < *pb ? -1 : 0;
}

int main()
{
    int *array;
    int n_values;
    int i;

    printf("How many value are there?");
    if (scanf("%d", &n_values) != 1 || n_values <= 0)
    {
        printf("Illegal number of values.\n");
        exit(EXIT_FAILURE);
    }
    array = malloc(n_values * sizeof(int));//分配内存
    if (array == NULL)
    {
        printf("Can't get memory for that many values.\n");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < n_values; i++)//读取数值
    {
        printf("?");
        if (scanf("%d", array + i) != 1)
        {
            printf("Error reading value #%d\n", i);
            free(array);
            exit(EXIT_FAILURE);
        }
    }
    qsort(array, n_values, sizeof(int), compare_integers);//排序(库函数)

    for (i = 0; i < n_values; i++)
        printf("%d\n", array[i]);

    free(array);
    return EXIT_SUCCESS;
}


运行:

用于保存这个列表的内存是动态分配的,这样就不必担心不知道用户希望对多少个值进行排序。他实际分配的内存就是实际需要的内存,不会造成浪费。

b. 复制字符串

#include<stdlib.h>
#include<stdio.h>

char * strdup(char const *string)
{
    char *new_string;
    new_string = malloc(strlen(string) + 1); 

    if (new_string != NULL)
        strcpy(new_string, string);

    return new_string;
}

strlen 不包含结束符,而 strcpy 是连同结束符 一起复制,所以这里要分配 比字符串长度多一个字节的内存,以便存储字符串结尾的NUL字节。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值