【C语言】内存管理(malloc, calloc, realloc, free),补充:perror和fprintf的区别

【C语言】内存通过指针来管理。指针变量存储内存地址,这个内存地址可以指向任何类型的变量。

指针变量声明:基类型 *指针变量名;

获取变量的内存地址:&变量;

指针指向变量的内存地址:指针变量名=&变量;

获取指针指向的内存地址的值:*指针变量名;

内存管理的函数:malloc, calloc, realloc, free均是标准库stdlib.h中的函数。

malloc:动态分配内存空间,堆区分配指定大小的内存用于存放数据,值不会被初始化。

calloc:动态分配内存空间,空间大小可定制,每个字节的值都初始化为0。

realloc:重新分配内存,原来的内存块重新扩展到新的大小,可能新的内存地址。

free:释放由malloc, calloc, realloc分配的内存空间。释放后该内存可分配给其它用途。

void free(void *ptr);

注:参数ptr是指向已分配内存块的指针。

       不返回任何值。

1、malloc, free

void *malloc(size_t size);

注:参数size是size_t类型(无符号整型)的值,即需要分配的内存块的大小(单位:字节)。

       返回void类型的指针,指向分配的内存块。若分配失败,返回NULL。

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

int main(void)
{
    int *numbers;      // 声明指针变量
    numbers = (int *)malloc(5 * sizeof(int));        // 分配内存空间
    // 判断内存分配是否成功,若失败,则打印错误信息并退出程序
    if(numbers == NULL)
    {
        perror("Memory alloation failed");
        return 1;
    }
    // 使用分配的内存空间
    for(int i = 0;i < 5;i++)
    {
        numbers[i] = i + 1;
    }
    // 输出分配的内存内容
    for(int i = 0;i < 5;i++)   
    {
        printf("\"numbers\", data %d is %d\n",i , numbers[i]);
    }
    // 释放分配的内存空间,避免内存泄漏
    free(numbers); 
    // 指针设为NULL,避免指针悬空(野指针)
    numbers = NULL;
    return 0;
}

// 结果:
"numbers", data 0 is 1
"numbers", data 1 is 2
"numbers", data 2 is 3
"numbers", data 3 is 4
"numbers", data 4 is 5

2、calloc, free

void *calloc(size_t num, size_t size);

注:参数num是需要被分配的元素个数。参数size是每个元素的大小(单位:字节)。

       返回void类型的指针,指向分配的内存块。若分配失败,返回NULL.

       每个字节的初始化的值为0。

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

int main(void)
{    
    char *strings;
    strings = (char *)calloc(6, sizeof(char));    // 分配内存空间,6个字符大小的内存空间,初始值都为0
    // 判断内存分配是否成功,若失败,则打印错误信息并退出程序
    if(strings == NULL)
    {
        fprintf(stderr, "Memory allocation failed");
        return 1;
    }
    // 打印初始值
    for(int i = 0;i < 6;i++)
    {
        printf("Before: strings=%s, data %i is %d\n", strings, i, strings[i]);
    }
    // 使用分配的内存空间
    for(int i = 0;i < 6;i++)
    {
        strings[i] = (char) (65 + i);     // ASCII码中:65-A
    }
    // 输出分配的内存内容
    for(int i = 0;i < 6;i++)
    {
        printf("After: strings=%s, data %i is %c\n", strings, i, strings[i]);
    }
    // 释放分配的内存空间,避免内存泄漏
    free(strings);
    // 指针设为NULL,避免指针悬空(野指针)
    strings = NULL;
    return 0;
}

// 结果为:
Before: strings=, data 0 is 0
Before: strings=, data 1 is 0
Before: strings=, data 2 is 0
Before: strings=, data 3 is 0
Before: strings=, data 4 is 0
Before: strings=, data 5 is 0
After: strings=ABCDEF, data 0 is A
After: strings=ABCDEF, data 1 is B
After: strings=ABCDEF, data 2 is C
After: strings=ABCDEF, data 3 is D
After: strings=ABCDEF, data 4 is E
After: strings=ABCDEF, data 5 is F

3、realloc, free

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

注:参数ptr是指向原分配内存块的指针。参数newsize是新的内存块大小(单位:字节)。

       返回void类型的指针,指向重新分配后的内存块。若重新分配失败,返回NULL;原内存块仍有效,不会被释放。

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

int main(void)
{
    char *s;
    s = (char *)malloc(5 * sizeof(char));      // 分配内存空间
    // 判断内存分配是否成功,若失败,则打印错误信息并退出程序
    if(s == NULL)
    {
        perror("Memory allocation failed");
        return 1;
    }
    else
    {
        strcpy(s, "hello");     // 使用分配的内存空间, strcpy:复制字符串
    }
    // 输出分配的内存内容
    for(int i = 0; i < 5 ;i++)
    {
        printf("s=%s, data %d is %c\n", s, i, s[i]);
    }
    printf("\n");

    // 重新分配内存空间,增加5个字符的空间(共10个字符)
    s = (char *)realloc(s, 10 * sizeof(char));
    if(s == NULL)
    {
        perror("Memory allocation failed");
        free(s);                // 释放原来的内存空间
        return 1;
    }
    // 使用重新分配的内存空间, strcat:字符串末尾追加内容
    strcat(s, "world");
    // 输出重新分配的内存内容
    for(int i = 0; i < 10 ;i++)
    {
        printf("s=%s, data %d is %c\n", s, i, s[i]);
    }
    // 释放分配的内存空间,避免内存泄漏
    free(s);
    // 指针设为NULL,避免指针悬空(野指针)
    s = NULL;

    return 0;
}

// 结果为:
s=hello, data 0 is h
s=hello, data 1 is e
s=hello, data 2 is l
s=hello, data 3 is l
s=hello, data 4 is o

s=helloworld, data 0 is h
s=helloworld, data 1 is e
s=helloworld, data 2 is l
s=helloworld, data 3 is l
s=helloworld, data 4 is o
s=helloworld, data 5 is w
s=helloworld, data 6 is o
s=helloworld, data 7 is r
s=helloworld, data 8 is l
s=helloworld, data 9 is d

补充:perror和fprintf的区别:

perror fprintf
void perror(const char *str) int fprintf(FILE *stream, const char *format,...)
提供前缀字符串(自定义信息,在系统定义的错误信息之前) 提供格式
输出错误信息 格式化输出
输出到stderr

可以标准输出stdout,

也可以输出到指定文件

自动包含系统定义的错误描述 构建错误信息
不返回任何值 若成功,返回写入的字符总数,否则返回-1

相关推荐

  1. C语言指针内存管理

    2024-03-25 20:24:01       35 阅读
  2. C语言内存管理以及堆空间栈空间区别

    2024-03-25 20:24:01       39 阅读
  3. C语言stderr、errno、strerror、perror

    2024-03-25 20:24:01       32 阅读
  4. C语言动态内存管理

    2024-03-25 20:24:01       15 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-25 20:24:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-25 20:24:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-25 20:24:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-25 20:24:01       20 阅读

热门阅读

  1. 2019南京大学计算机考研复试机试题-Stepping Numbers

    2024-03-25 20:24:01       15 阅读
  2. Nginx配置文件中Location指令的匹配优先级

    2024-03-25 20:24:01       17 阅读
  3. 【微服务设计】常见的DDD设计中的经验教训!

    2024-03-25 20:24:01       19 阅读
  4. 计算机网络原理之四种攻击

    2024-03-25 20:24:01       21 阅读
  5. Android中的设计模式

    2024-03-25 20:24:01       18 阅读
  6. 异常的处理(try-catch-finally)

    2024-03-25 20:24:01       15 阅读
  7. C语言空指针常量NULL

    2024-03-25 20:24:01       16 阅读
  8. python内置函数 T

    2024-03-25 20:24:01       20 阅读
  9. 约瑟夫问题---(蓝桥杯)

    2024-03-25 20:24:01       22 阅读
  10. Rancher(v2.6.3)——Rancher部署Nginx(单机版)

    2024-03-25 20:24:01       18 阅读
  11. Leetcode 28:找出字符串中第一个匹配项的下标

    2024-03-25 20:24:01       19 阅读