- C编程教程
- C - 首页
- C语言基础
- C - 概述
- C - 特性
- C - 历史
- C - 环境设置
- C - 程序结构
- C - Hello World
- C - 编译过程
- C - 注释
- C - 词法单元
- C - 关键字
- C - 标识符
- C - 用户输入
- C - 基本语法
- C - 数据类型
- C - 变量
- C - 整数提升
- C - 类型转换
- C - 类型强制转换
- C - 布尔值
- C语言中的常量和字面量
- C - 常量
- C - 字面量
- C - 转义序列
- C - 格式说明符
- C语言中的运算符
- C - 运算符
- C - 算术运算符
- C - 关系运算符
- C - 逻辑运算符
- C - 位运算符
- C - 赋值运算符
- C - 一元运算符
- C - 自增和自减运算符
- C - 三元运算符
- C - sizeof 运算符
- C - 运算符优先级
- C - 其他运算符
- C语言中的决策
- C - 决策
- C - if 语句
- C - if...else 语句
- C - 嵌套if语句
- C - switch 语句
- C - 嵌套switch语句
- C语言中的循环
- C - 循环
- C - while 循环
- C - for 循环
- C - do...while 循环
- C - 嵌套循环
- C - 无限循环
- C - break 语句
- C - continue 语句
- C - goto 语句
- C语言中的函数
- C - 函数
- C - 主函数
- C - 按值调用函数
- C - 按引用调用函数
- C - 嵌套函数
- C - 可变参数函数
- C - 用户定义函数
- C - 回调函数
- C - 返回语句
- C - 递归
- C语言中的作用域规则
- C - 作用域规则
- C - 静态变量
- C - 全局变量
- C语言中的数组
- C - 数组
- C - 数组的特性
- C - 多维数组
- C - 将数组传递给函数
- C - 从函数返回数组
- C - 变长数组
- C语言中的指针
- C - 指针
- C - 指针和数组
- C - 指针的应用
- C - 指针运算
- C - 指针数组
- C - 指针到指针
- C - 将指针传递给函数
- C - 从函数返回指针
- C - 函数指针
- C - 指向数组的指针
- C - 指向结构体的指针
- C - 指针链
- C - 指针与数组
- C - 字符指针和函数
- C - 空指针
- C - void 指针
- C - 悬空指针
- C - 解引用指针
- C - 近、远和巨型指针
- C - 指针数组的初始化
- C - 指针与多维数组
- C语言中的字符串
- C - 字符串
- C - 字符串数组
- C - 特殊字符
- C语言中的结构体和联合体
- C - 结构体
- C - 结构体和函数
- C - 结构体数组
- C - 自引用结构体
- C - 查找表
- C - 点(.)运算符
- C - 枚举(或枚举类型)
- C - 结构体填充和打包
- C - 嵌套结构体
- C - 匿名结构体和联合体
- C - 联合体
- C - 位域
- C - typedef
- C语言中的文件处理
- C - 输入与输出
- C - 文件I/O(文件处理)
- C预处理器
- C - 预处理器
- C - 预处理指令
- C - 预处理器运算符
- C - 宏
- C - 头文件
- C语言内存管理
- C - 内存管理
- C - 内存地址
- C - 存储类
- 其他主题
- C - 错误处理
- C - 可变参数
- C - 命令执行
- C - 数学函数
- C - static 关键字
- C - 随机数生成
- C - 命令行参数
- C编程资源
- C - 问答
- C - 快速指南
- C - 速查表
- C - 有用资源
- C - 讨论
C语言内存管理
C语言的一个重要特性是编译器管理代码中声明的变量的内存分配方式。一旦编译器分配了所需的内存字节,在运行时就无法更改。
编译器采用静态内存分配方法。但是,有时您可能需要在运行时按需分配内存。阅读本章以了解C语言中的动态内存管理是如何工作的。
C语言中动态内存管理的函数
C编程语言提供了一些用于动态内存分配和管理的函数。这些函数可以在<stdlib.h>头文件中找到。
函数 | 描述 |
---|---|
void *calloc(int num, int size); | 此函数分配一个包含num个元素的数组,每个元素的大小(以字节为单位)为size。 |
void free(void *address); | 此函数释放由address指定的内存块。 |
void *malloc(size_t size); | 此函数分配一个包含num个字节的数组,并将其保留为未初始化状态。 |
void *realloc(void *address, int newsize); | 此函数重新分配内存,将其扩展到newsize。 |
动态分配内存
如果您知道数组的大小,那么很容易定义它为一个数组。例如,如果您需要存储一个人的姓名,那么您可以安全地定义一个数组来保存最多100个字符(假设姓名不会超过100个字符)。因此,您可以按如下方式定义一个数组:
char name[100];
这是一个静态内存分配的例子。现在让我们考虑一种情况,您不知道需要存储的文本的长度,例如,您想存储有关某个主题的详细说明。在这种情况下,如果内容少于分配的大小,则在程序执行期间分配的内存会被浪费。
另一方面,如果所需的大小超过分配的内存大小,则可能导致不可预测的行为,包括导致数据损坏,因为数组的大小无法动态更改。
在这种情况下,您需要使用本章中描述的动态内存分配方法。
malloc() 函数
此函数在stdlib.h头文件中定义。它分配一个所需大小的内存块,并返回一个void指针。
void *malloc (size)
size参数指的是以字节为单位的内存块。要为指定的 数据类型分配内存,您需要使用类型强制转换运算符。
例如,以下代码片段分配了存储int类型所需的内存:
int *ptr; ptr = (int *) malloc (sizeof (int));
在这里,我们需要定义一个指向字符的指针,而无需定义需要多少内存,然后根据需要分配内存。
示例
以下示例使用malloc()函数分配存储字符串所需的内存(而不是声明固定大小的char数组):
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) malloc(strlen("TutorialsPoint")); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); } }
输出
当以上代码编译并执行时,会产生以下输出:
Name = TutorialsPoint
calloc() 函数
calloc()函数(代表连续分配)分配请求的内存并返回指向它的指针。
void *calloc(n, size);
这里,“n”是要分配的元素数量,“size”是每个元素的字节大小。
以下代码片段分配了存储10个int类型所需的内存:
int *ptr; ptr = (int *) calloc(25, sizeof(int));
示例
让我们使用calloc()函数重写以上程序。您只需将malloc替换为calloc即可:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); } }
因此,您可以完全控制,并且可以在分配内存时传递任何大小值,这与数组不同,数组一旦定义了大小,就不能更改。
调整内存大小和释放内存
当您的程序退出时,操作系统会自动释放程序分配的所有内存。但是,当您不再需要使用分配的内存时,最好通过调用free()函数显式释放分配的内存,这是一个良好的实践。
在本节中,我们将重点介绍两个函数realloc()和free()的使用,您可以使用它们来调整内存大小和释放分配的内存。
realloc() 函数
C语言中的realloc()(重新分配)函数用于动态更改先前分配的内存的内存分配。您可以通过调用realloc()函数来增加或减少已分配内存块的大小。
使用realloc()函数的原型如下:
void *realloc(*ptr, size);
这里,第一个参数“ptr”是指向以前使用malloc、calloc或realloc分配的内存块的指针,该内存块将被重新分配。如果它是NULL,则会分配一个新的块,并且函数会返回指向它的指针。
第二个参数“size”是以字节为单位的新内存块大小。如果它是“0”并且ptr指向现有的内存块,则ptr指向的内存块将被释放,并返回一个NULL指针。
示例
以下示例演示了如何在C程序中使用realloc()函数:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); name = (char *) realloc(name, strlen(" India Private Limited")); strcat(name, " India Private Limited"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); } }
输出
当以上代码编译并执行时,会产生以下输出:
Name = TutorialsPoint India Private Limited
free() 函数
C语言中的free()函数用于动态释放使用诸如malloc()和calloc()等函数分配的内存,因为它们不会自行释放。
在C编程中,任何对未使用的内存的引用都会产生垃圾堆积,这可能导致程序崩溃等问题。因此,明智的做法是使用free()函数对分配的内存执行手动清理操作。
以下是使用free()函数的原型:
void free(void *ptr);
其中ptr是指向先前分配的内存块的指针。
示例
以下示例演示了如何在C程序中使用free()函数:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char *name; name = (char *) calloc(strlen("TutorialsPoint"), sizeof(char)); strcpy(name, "TutorialsPoint"); if(name == NULL) { fprintf(stderr, "Error - unable to allocate required memory\n"); } else { printf("Name = %s\n", name); free(name); } }
输出
在代码的末尾,分配给char *指针的内存被释放。
Name = TutorialsPoint India Private Limited