C中的动态内存分配:malloc(),calloc()函数

发布于:2021-02-09 09:55:20

0

202

0

C malloc() calloc() 动态分配

在学习C动态内存分配之前,让我们先了解一下:

C中的内存管理是如何工作的?

当使用基本数据类型声明变量时,C编译器会自动为名为堆栈的内存池中的变量分配内存空间。

例如,一个float变量在声明时通常需要4个字节(根据平台)。我们可以使用sizeof操作符验证此信息,如下面的示例所示。

#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动态内存分配使用堆。

<stdlib.h>库具有负责动态内存管理的功能。

函数

目的

malloc()

分配请求大小的内存,并将指针返回到分配空间的第一个字节。

calloc()

为数组的元素分配空间。将元素初始化为零并返回指向内存的指针。

realloc()

它用于修改先前分配的内存空间的大小。

Free()

释放或清空先前分配的内存空间。

我们来讨论一下上述函数及其应用。

C malloc()函数

C malloc()函数表示内存分配。它是一个用于动态分配内存块的函数。它保留指定大小的内存空间,并返回指向内存位置的空指针。返回的指针通常是void类型。这意味着我们可以将C malloc()函数赋给任何指针。

malloc()函数的语法:

ptr = (cast_type *) malloc (byte_size);

  • ptr是cast类型的指针。

  • C malloc()函数返回一个指向字节大小的分配内存的指针。

malloc()的示例:

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

 

  1. 注意,sizeof(*ptr)被用来代替sizeof(int),以便在以后将*ptr声明类型转换为不同的数据类型时使代码更加健壮。

  2. 如果内存不足,分配可能会失败。在本例中,它返回一个空指针。因此,应该包含检查空指针的代码。

  3. 请记住,分配的内存是连续的,可以将其视为数组。我们可以使用指针算法来访问数组元素,而不是使用括号[]。我们建议使用+来引用数组元素,因为使用incrementation++或+=会更改指针存储的地址。

Malloc()函数还可以与字符数据类型以及复杂数据类型(如结构)一起使用。

free()函数

在编译时自动释放变量的内存。在动态内存分配中,必须显式释放内存。如果不这样做,您可能会遇到内存不足错误。

调用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():关键区别

以下是C中malloc()和calloc()的主要区别:

calloc()函数通常比malloc()函数更合适、更有效。虽然这两个函数都用于分配内存空间,但calloc()可以一次分配多个块。你不必每次都请求内存块。calloc()函数用于需要较大内存空间的复杂数据结构中。

由C中的calloc()分配的内存块总是初始化为零,而在C中的函数malloc()中,它总是包含一个垃圾值。

C realloc()函数

使用Crealloc()函数,可以向已分配的内存添加更多内存大小。它在保持原始内容不变的同时扩展当前块。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 = %un", ptr, ptr);

  ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size
  strcat(ptr, " In 'C'");
  printf(" %s,  Address = %un", ptr, ptr);
  free(ptr);
  return 0;
}

每当C中的realloc()导致一个不成功的操作时,它都会返回一个空指针,并且之前的数据也会被释放。

C语言中的动态数组

C语言中的动态数组允许元素的数量根据需要增长。C动态数组在计算机科学算法中有着广泛的应用。

在下面的程序中,我们在C中创建了一个动态数组并调整了其大小。

#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]=%dn", i, arr_dynamic[i]);
       elements = 4;
       arr_dynamic = realloc(arr_dynamic, elements * sizeof(int)); //reallocate 4 elements
       printf("After reallocn");
       for (i = 2; i < elements; i++) arr_dynamic[i] = i;
       for (i = 0; i < elements; i++) printf("arr_dynamic[%d]=%dn", 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()函数用于清除动态分配的内存。