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

本文主要是介绍【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 os=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的区别:

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

可以标准输出stdout,

也可以输出到指定文件

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

这篇关于【C语言】内存管理(malloc, calloc, realloc, free),补充:perror和fprintf的区别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/847319

相关文章

gradle第三方Jar包依赖统一管理方式

《gradle第三方Jar包依赖统一管理方式》:本文主要介绍gradle第三方Jar包依赖统一管理方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录背景实现1.顶层模块build.gradle添加依赖管理插件2.顶层模块build.gradle添加所有管理依赖包

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

Spring 基于XML配置 bean管理 Bean-IOC的方法

《Spring基于XML配置bean管理Bean-IOC的方法》:本文主要介绍Spring基于XML配置bean管理Bean-IOC的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一... 目录一. spring学习的核心内容二. 基于 XML 配置 bean1. 通过类型来获取 bean2. 通过

go 指针接收者和值接收者的区别小结

《go指针接收者和值接收者的区别小结》在Go语言中,值接收者和指针接收者是方法定义中的两种接收者类型,本文主要介绍了go指针接收者和值接收者的区别小结,文中通过示例代码介绍的非常详细,需要的朋友们下... 目录go 指针接收者和值接收者的区别易错点辨析go 指针接收者和值接收者的区别指针接收者和值接收者的

在Spring Boot中浅尝内存泄漏的实战记录

《在SpringBoot中浅尝内存泄漏的实战记录》本文给大家分享在SpringBoot中浅尝内存泄漏的实战记录,结合实例代码给大家介绍的非常详细,感兴趣的朋友一起看看吧... 目录使用静态集合持有对象引用,阻止GC回收关键点:可执行代码:验证:1,运行程序(启动时添加JVM参数限制堆大小):2,访问 htt

售价599元起! 华为路由器X1/Pro发布 配置与区别一览

《售价599元起!华为路由器X1/Pro发布配置与区别一览》华为路由器X1/Pro发布,有朋友留言问华为路由X1和X1Pro怎么选择,关于这个问题,本期图文将对这二款路由器做了期参数对比,大家看... 华为路由 X1 系列已经正式发布并开启预售,将在 4 月 25 日 10:08 正式开售,两款产品分别为华