C和指针读书笔记(第十一章)

1. C函数库提供了两个函数:malloc和free,分别用于动态内存的分配和释放。这些函数维护一个可用内存池。当一个程序需要一些内存时,它就调用malloc函数从内存池取一块合适的内存,并向程序返回一个指向这块内存的指针。此时内存并未初始化。当一块以亲分配的内存不再使用时,程序调用free函数把他归还给内存池共以后需要。

//stdlib.h头文件中声明
void *malloc(size_t size);
void free(void *pointer);

malloc的参数就是需要分配的内存字节(字符)数,如果内存中的可用内存可以满足这个要求,malloc就返回一个指向被分配的内存块起始位置的指针。如果内存池无法满足请求,malloc会申请更多的内存,并在新申请的内存上分配任务,如果无法分配更多内存,malloc就返回一个NULL指针。因此对每个从malloc返回的指针都必须检查其值非NULL。
malloc返回*void指针,可以转换成其他任何类型的指针。


2. 另外两个内存分配函数:calloc和realloc

void *calloc(size_t nu_ele. size_t ele_size);
//参数为“所需元素的数量”和“每个元素的字节数”
void *realloc(void *ptr, size_t new_size);

calloc也用于分配内存,calloc在返回指向内存的指针之前把它初始化为0。
realloc函数用于修改一个原先已经分配内存块的大小。通过realloc可以是一块内存扩大或缩小,如果扩大内存块,那么这块 内存原先的内容依然保留,新增加的内存添加到原先内存块的后面,新内存并未以任何方法初始化。如果缩小内存块,该内存块尾部的部分内容被拿掉,剩余部分内存依然保留。
如果原先的部分无法改变大小,realloc将分配另一块正确大小的内存大小,并将原先那块内存的内容复制到新的块上,因此在使用realloc后,就不能在使用指向旧内存的指针而是改用realloc所返回的新指针。
如果第一个参数是NULL,那么realloc和malloc的函数功能一样


3. 动态内存分配的常见错误:

  • 对NULL指针进行解引用
  • 对分配的内存进行操作时越过边界
  • 释放并非动态分配的内存
  • 释放一块动态分配内存的一部分
  • 一块动态内存被释放之后被继续使用

4. 动态分配内存的一个常见用途就是为那些长度在运行时才知道的数组分配内存空间。

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

//读取、排列和打印一列整数值

//该函数由'qsort'调用,用于比较整型值
int compare_int(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("请输入要排序的数值的数量:");
    if(scanf("%d", &n_values) != 1 || n_values <= 0){
        printf("数值的数量错误\n");
        exit(EXIT_FAILURE);
    }

    //分配内存,用于存储这些值
    array = malloc(n_values * sizeof(int));
    if(array == NULL){
        printf("无法为这些数值申请内存空间");
        exit(EXIT_FAILURE);
    }

    //读取这些值
    for(i = 0; i < n_values; i += 1){
        printf("请输入数值 ");
        if(scanf("%d", array + i) != 1){
            printf("错误读取数值 #%d\n", i);
            free(array);
            exit(EXIT_FAILURE);
        }
    }

    //对这些值进行排序
    qsort(array, n_values, sizeof(int), compare_int);

    //打印这些值
    for(i = 0; i < n_values; i += 1){
        printf("%d\n", array[i]);
    }

    //释放内存并退出
    free(array);
    return EXIT_SUCCESS;

}

5. 读取字符串时,如果预先不知道字符串的长度,就无法使用普通数组作为缓冲区,反之可以使用动态分配内存。当发现一个长度超过缓冲区的输入行就可以重新分配一个更大的缓冲区,把该行的剩余部分也装进去。

#include <stdlib.h>
#include <string.h>

char *strdup(char const *string);
int main(void)
{
    char s[] = "closer";
    char *pc;
    pc = strdup(s);
    printf("%c%c%c%c%c%c\n",*pc, *(pc + 1), *(pc + 2), *(pc+ 3), *(pc + 4), *(pc + 5));  //closer

    return 0;
}

//用动态分配内存制作字符串的一个拷贝,
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;
    }
}

2016.10.11

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值