C/C++中的calloc()函数

581 阅读5分钟

在这篇文章中,我们已经解释了C/C++中calloc()函数的使用,它被用于动态内存分配。我们用不同情况的代码例子来解释它。

目录

  1. 什么是Calloc?
  2. 什么是动态内存分配?
  3. calloc()的例子
  4. calloc() vs malloc()
  5. calloc():优点和缺点

让我们开始学习C/C++中的calloc()。

什么是calloc?

C语言中的calloc()"连续分配 "函数(由于向后兼容:C++)为一个对象阵列分配一个内存块,并将其所有位初始化为零,如果分配成功,它返回一个指向所分配内存块的第一个字节的指针。

如果大小为零,返回的值取决于库的实现。它可能是也可能不是一个空指针。

但是在我们讨论calloc()函数之前,我们需要了解动态内存分配的概念。

Dynamic Memory Allocation concepts

*上图:calloc()分配内存和初始化

什么是动态内存分配?

有没有遇到过这样的问题:你事先不知道你需要多少内存?

动态内存是一种结构化编程程序,允许用户在程序运行时分配内存。

通过动态内存分配,我们可以在程序的执行过程中分配或删除内存。通过这样做,它避免了计算机内存的浪费。

在<stdlib.h>头文件下定义的C语言提供了3个库函数来实现C语言编程中的动态内存分配。

  • malloc()
  • calloc()
  • realloc()

在这篇文章中,我们将重点讨论calloc()

calloc()的例子

让我们看看一些带有语法的calloc()的使用案例

使用calloc()

ptr = (cast-type*)calloc(n, element-size);
  • cast_type:Cast类型是你想分配内存的数据类型
  • n:n是元素的数量
  • element-size:每个元素的大小

返回值

该函数返回一个指向所分配内存的指针,如果请求失败则返回NULL

例子:演示使用calloc()和free()的程序

下面的程序使用calloc()分配内存来存储数字,然后从用户那里获得数字输入,然后打印出数字和它们的总和。
做完这些后,它使用free()释放分配的内存

#include <stdio.h>  
#include <conio.h>  
#include <stdlib.h>  
void main()  {     
    int n, *ptr, *p, i, sum = 0;   
    printf (" Enter the number of elements: ");  
    scanf (" %d", &n);  
        
    ptr = (int *) calloc (n, sizeof(int));  
    p = ptr; 
    if (ptr == NULL) {    
        printf (" Memory is not allocated. ");  
        exit(0);  
    }  
    printf (" Enter %d numbers \n", n);  
    for ( i = 1; i <= n; i++){  
        scanf ( "%d", ptr);  
        sum = sum + *ptr;  
        ptr++;  
    }  
      
    printf (" Elements are: ");  
    for (i = 1;  i <= n; i++){  
        printf (" %d", *p);  
    p++;  
    }  
    printf (" \n The addition of the elements is: %d ", sum);  
    free(ptr);
    getch();  
}  

输出

Enter the number of elements: 5
 Enter 5 numbers
1
2
3
4
5
 Elements are:  1 2 3 4 5
 The addition of the elements is: 15

下面是对上述程序的逐步解释

  1. 声明我们的变量和指针
int n, *ptr, *p, i, sum = 0; 
  • **n:**元素的数量
  • *ptr**:**存储动态内存的基本地址
  • *p**:**存储*ptr的临时地址
  • **i:**用于迭代循环
  • sum: 存储总和
  1. 从用户那里获取元素的数量
printf (" Enter the number of elements: ");  
scanf (" %d", &n); 
  1. 使用calloc来创建一个整数数据类型的内存块
ptr = (int *) calloc (n, sizeof(int));  
  1. 分配指针的地址
p = ptr;
  1. 检查内存是否被分配

如果ptr指向NULL,意味着它还没有被分配

if (ptr == NULL) {   
        printf (" Memory is not allocated. ");  
        exit(0);   
    }  
  1. 输入数字并计算它的总和
printf (" Enter %d numbers \n", n);  
    for ( i = 1; i <= n; i++){  
        scanf ( "%d", ptr);  
        sum = sum + *ptr;  
        ptr++;  
    }  
  1. 显示数字和它的总和
printf (" Elements are: ");  
    for (i = 1;  i <= n; i++){  
        printf (" %d", *p);  
    p++;  
    }  
printf (" \n The addition of the elements is: %d ", sum);  
  1. 使用free()释放分配的空间
free(ptr);
getch();

free()是C语言中的一个方法,用于动态地释放内存。

calloc()的更多用例

在C语言中对结构体使用calloc()

#include <stdio.h>

struct employee {
    char *name;
    int salary;
};
typedef struct employee emp;

int main() {
    emp *e1;
    e1 = (emp*)calloc(30,sizeof(emp));
    
    return 0;
}

在C++中对类使用calloc()

#include <stdio.h>

class MyClass {     
  public:             
    int myNum;        
    string myString; 
};

int main(){
    MyClass *MyObj;
    MyObj = (MyClass*)calloc(10,sizeof(MyClass));
    
    return 0;
}

现在让我们看看calloc()与malloc()的比较,后者是另一个用于内存分配的C库函数

calloc()和malloc()的比较

要比较calloc()和malloc(),我们首先要对malloc()的特点有一个基本的了解

malloc()

关键点:

  • malloc()代表"内存分配"
  • 该方法用于动态分配所需大小的单个大内存块
  • 它返回一个void类型的指针,该指针可以被投射到任何形式的指针中

语法

mp = (cast_type*) malloc(byte_size);
  • mp:指针 mp持有分配的内存中第一个字节的地址。
  • cast_type:它决定了分配的内存的数据类型。
  • byte_size:它帮助我们确定分配的内存的字节数。

返回值

该函数返回一个指向所分配内存的指针,如果请求失败则返回NULL。

我们可以通过使用malloc()+memset(0)实现与calloc()相同的功能。

ptr = malloc(size);
memset(ptr, 0, size);

malloc()和calloc()的区别

  • calloc()可以为一个变量分配多个内存块,而malloc()只创建一个由用户指定大小的内存块。
  • calloc()分配的内存块总是初始化为0,而malloc()在分配时不进行初始化,因此返回一个垃圾值。
  • calloc()需要两个参数,而malloc()只需要一个参数。
  • calloc()比malloc()慢,但它的时间效率更高。

阅读更多关于calloc() vs malloc() vs realloc() 的比较

calloc():优点和缺点

优点:

  • 如果你想把内存初始化为0,那么你可以使用calloc(),使用malloc(),然后用memset(0)来初始化它是比较费钱的。
  • calloc()可以帮助你防止整数溢出的漏洞:
    比较一下。
size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

前者可能导致微小的分配和随后的缓冲区溢出,如果count大于SIZE_MAX/sizeof *bar 。后者在这种情况下会自动失败,因为不能创建这么大的对象。

缺点

  • calloc()在你声明内存块时将其初始化为0,所以初始化你的内存块需要一些时间。出于性能的考虑,请使用malloc()而不是calloc()。

什么时候使用calloc()?

  • 为一个结构分配内存,你希望所有的成员都初始化为0。
  • 为一个字符数组分配内存,随后你要将一些字符写入该数组,然后将其作为一个NULL结束的字符串。
  • 为一个指针数组分配内存,你想把它初始化为NULL。

什么时候不使用calloc()?

  • 如果你不需要动态分配的内存是零初始化的,那么就使用malloc。

现在我们来测试一下你的理解。

问题

以下哪项是/是正确的?

calloc()分配内存的同时也将分配的内存初始化为零,而使用malloc()分配的内存有随机数据。

malloc()和memset()可以用来获得与calloc()相同的效果。

malloc()和calloc()都返回'void '指针。

以上都是

自我解释

通过OpenGenus的这篇文章,你一定对C/C++编程中的calloc()有了深刻的认识。