使用 malloc()、calloc() 函数在 C 语言中进行动态内存分配
在学习 C 动态内存分配之前,让我们先了解:
C 语言中的内存管理如何工作?
当你使用基本数据类型声明一个变量时,C 编译器会自动在内存池中为该变量分配内存空间,该内存池称为 堆.
例如,声明一个浮点变量时,它通常占用 4 个字节(根据平台)。我们可以使用 大小 运算符如下例所示
#include <stdio.h> int main() { float x; printf("The size of float is %d bytes", sizeof(x)); return 0;}
输出将是:
The size of float is 4 bytes
此外,具有指定大小的数组被分配在连续的内存块中,每个块都有一个元素的大小:
#include <stdio.h> int main() { float arr[10]; printf("The size of the float array with 10 element is %d", sizeof(arr)); return 0;}
结果是:
The size of the float array with 10 element is 40
到目前为止,我们已经知道,声明基本数据类型或数组时,内存是自动管理的。但是,C 语言中有一个分配内存的过程,它允许您实现一个程序,其中数组大小在运行程序(运行时)之前是不确定的。这个过程称为“动态内存分配设立的区域办事处外,我们在美国也开设了办事处,以便我们为当地客户提供更多的支持。“
C 中的动态内存分配
动态内存分配 是根据您的编程需要手动分配和释放内存。动态内存由指向我们称为堆的区域中新分配的内存空间的指针管理和提供。
现在,您可以在运行时动态创建和销毁元素数组,而不会出现任何问题。总而言之,自动内存管理使用堆栈,而 C 动态内存分配使用堆。
这库具有负责动态内存管理的函数。
功能 | 目的 |
---|---|
malloc() | 分配请求大小的内存并返回指向第一个字节的指针 已分配空间。 |
调用() | 为数组元素分配空间。将元素初始化为零并返回指向内存的指针。 |
重新分配() | 用于修改先前分配的内存空间的大小。 |
自由的() | 释放或清空先前分配的内存空间。 |
让我们讨论一下上述函数及其应用
C 语言中的 malloc() 函数
C malloc() 函数代表内存分配。它是一个用于动态分配内存块的函数。它保留指定大小的内存空间并返回指向内存位置的空指针。返回的指针通常为 void 类型。这意味着我们可以将 C malloc() 函数分配给任何指针。
malloc() 函数的语法:
ptr = (cast_type *) malloc (byte_size);
在这里,
- ptr 是 cast_type 的指针。
- C malloc() 函数返回指向分配的 byte_size 内存的指针。
malloc()的示例:
Example: ptr = (int *) malloc (50)
当该语句执行成功后,会保留50字节的内存空间,保留空间第一个字节的地址赋给int类型的指针ptr。
考虑另一个例子:
#include <stdlib.h> int main(){ int *ptr; ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */ if (ptr != NULL) { *(ptr + 5) = 480; /* assign 480 to sixth integer */ printf("Value of the 6th integer is %d",*(ptr + 5)); } }
输出:
Value of the 6th integer is 480
- 注意到 sizeof(*ptr) 被用来代替 大小(int) 以便在稍后将 *ptr 声明转换为不同的数据类型时使代码更加健壮。
- 如果内存不足,分配可能会失败。在这种情况下,它会返回一个 NULL 指针。因此,您应该包含代码来检查 NULL 指针。
- 请记住,分配的内存是连续的,可以将其视为数组。我们可以使用指针算法来访问数组元素,而不是使用括号 [ ]。我们建议使用 + 来引用数组元素,因为使用增量 ++ 或 += 会更改数组存储的地址 指针.
Malloc() 函数还可以与字符数据类型以及结构等复杂数据类型一起使用。
C 语言中的 free() 函数
记忆 变量 在编译时自动释放。在动态内存分配中,您必须明确释放内存。如果不这样做,您可能会遇到内存不足错误。
免费() 在 C 语言中,函数被调用来释放/分配内存。通过释放程序中的内存,您可以释放更多的内存以供以后使用。
例如:
#include <stdio.h> int main() { int* ptr = malloc(10 * sizeof(*ptr)); if (ptr != NULL){ *(ptr + 2) = 50; printf("Value of the 2nd integer is %d",*(ptr + 2)); } free(ptr); }
输出:
Value of the 2nd integer is 50
C 语言中的 calloc() 函数
C calloc() 函数代表连续分配。此函数用于分配多个内存块。它是一个动态内存分配函数,用于将内存分配给复杂的数据结构,例如数组和结构。
Malloc() 函数用于分配单块内存空间,而 C 中的 calloc() 用于分配多块内存空间。calloc() 函数分配的每个块大小相同。
calloc() 函数的语法:
ptr = (cast_type *) calloc (n, size);
- 上述语句用于分配n个大小相同的内存块。
- 分配内存空间后,所有字节都被初始化为零。
- 返回当前位于分配的内存空间第一个字节的指针。
每当分配内存空间出现错误(例如内存不足)时,就会返回空指针。
calloc()的示例:
下面的程序计算算术序列的总和。
#include <stdio.h> int main() { int i, * ptr, sum = 0; ptr = calloc(10, sizeof(int)); if (ptr == NULL) { printf("Error! memory not allocated."); exit(0); } printf("Building and calculating the sequence sum of the first 10 terms \ n "); for (i = 0; i < 10; ++i) { * (ptr + i) = i; sum += * (ptr + i); } printf("Sum = %d", sum); free(ptr); return 0; }
结果:
Building and calculating the sequence sum of the first 10 terms Sum = 45
calloc() 与 malloc():主要区别
以下是 malloc() 与 calloc() 在C中:
calloc() 函数通常比 malloc() 函数更合适、更高效。虽然这两个函数都用于分配内存空间,但 calloc() 可以一次分配多个块。您不必每次都请求一个内存块。calloc() 函数用于需要更大内存空间的复杂数据结构。
C 语言中 calloc() 分配的内存块始终初始化为零,而在 C 语言中的 malloc() 函数中,它始终包含垃圾值。
C 语言中的 realloc() 函数
使用 C 重新分配() 函数,您可以向已分配的内存添加更多内存大小。它扩展当前块,同时保留原始内容。C 中的 realloc() 代表内存重新分配。
realloc() 还可用于减少先前分配的内存的大小。
realloc() 函数的语法:
ptr = realloc (ptr,newsize);
上述语句在变量 newsize 中分配了一个新的具有指定大小的内存空间。执行该函数后,指针将返回到内存块的第一个字节。新大小可以大于或小于以前的内存。我们无法确定新分配的块是否指向与前一个内存块相同的位置。此函数将复制新区域中所有以前的数据。它确保数据保持安全。
realloc()的示例:
#include <stdio.h> int main () { char *ptr; ptr = (char *) malloc(10); strcpy(ptr, "Programming"); printf(" %s, Address = %u\n", ptr, ptr); ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size strcat(ptr, " In 'C'"); printf(" %s, Address = %u\n", ptr, ptr); free(ptr); return 0; }
每当C语言中的realloc()操作不成功时,它都会返回一个空指针,并且先前的数据也会被释放。
#include <stdio.h> int main() { int * arr_dynamic = NULL; int elements = 2, i; arr_dynamic = calloc(elements, sizeof(int)); //Array with 2 integer blocks for (i = 0; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); elements = 4; arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements printf("After realloc\n"); for (i = 2; i < elements; i++) arr_dynamic[i] = i; for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%d\n", i, arr_dynamic[i]); free(arr_dynamic); }
屏幕上的 C 动态数组程序结果:
arr_dynamic[0]=0 arr_dynamic[1]=1 After realloc arr_dynamic[0]=0 arr_dynamic[1]=1 arr_dynamic[2]=2 arr_dynamic[3]=3
总结
- 我们可以通过在堆中根据需要创建内存块来动态管理内存
- 在 C 动态内存分配中,内存是在运行时分配的。
- 动态内存分配允许操作字符串和数组,其大小灵活,可以在程序中随时更改。
- 当您不知道特定结构将占用多少内存时,它是必需的。
- C 语言中的 Malloc() 是一个动态内存分配函数,它代表内存分配,将特定大小的内存块初始化为垃圾值
- C 语言中的 Calloc() 是一个连续的内存分配函数,它一次分配多个初始化为 0 的内存块
- C 语言中的 Realloc() 用于根据指定的大小重新分配内存。
- Free()函数用于清除动态分配的内存。