34

为什么calloc需要两个参数而不是一个 like malloc

具体来说,由于以下表达式之间(或是否存在?)之间没有区别:

calloc (a, b);
calloc (b, a);
calloc (a * b, 1);
calloc (1, a * b);

为什么不接受要分配的总字节数?这个界面背后的基本原理是什么?为什么这不适用于malloc?

4

5 回答 5

12

对于为什么它有两个论点,我听到了两个 [互斥的] 解释:

  1. calloc负责检查乘法溢出。如果请求块的总大小太大(如溢出size_t),calloc则返回空指针以指示失败。malloc你必须注意自己的溢出,许多人只是忘记这样做。(尽管标准库的历史知道calloc忽略溢出的实现示例,因此工作不正确)。

  2. calloc实际上允许分配比 type 范围更大的内存块size_t,即calloc可能能够对其参数执行适当的非溢出大乘法并分配结果大小的块。出于这个原因,由于calloc使用了两个类型的参数size_t,它可以分配比malloc以往更大的块(因为malloc只需要一个类型的参数size_t)。

我一直相信第一个解释是正确的。但是,在阅读了一些关于 SO 的帖子后,我对此表示怀疑。

于 2010-11-03T03:11:57.710 回答
4

我相信 malloc 保证返回一个内存区域,该区域根据与第二个参数指示的大小兼容的最粗略要求对齐。例如,如果系统要求对齐 2 字节和 4 字节整数,并且第二个参数是 10,则返回的指针必须对齐在双字节边界上;如果第二个参数是 12,则指针将在四字节边界上对齐。我怀疑实际上许多系统会将所有返回的指针对齐到可能需要的最大边界,无论大小如何,但我认为除了 calloc 之外不需要它。

于 2010-11-03T03:27:40.807 回答
0

calloc(x,y)相当于malloc(x*y)

但是calloc做额外的(将值设置为0)memset(block, 0, x*y)

此函数仅用于传递元素的大小和元素当在 malloc 中您必须将此值相乘以获得所需的字节数,此函数在乘法中也检查整数溢出。

例如,如果你想为 12 个整数分配内存并且你想用这个整数做一些事情,你必须将她的值设置为 0,使用calloc(12, sizeof(int))

但是,如果您想分配一些内存块(256 字节)以在将来复制一些字符串,那么memset对您来说不可用,那么更好的用途是malloc(sizeof(char) * 256)或者例如malloc(sizeof(wchar_t) * 256)


void *
calloc (size_t nmemb, size_t lsize)
{
  void *ptr;
  struct __meminfo *info;
  size_t size = lsize * nmemb;

  /* if size overflow occurs, then set errno to ENOMEM and return NULL */
  if (nmemb && lsize != (size / nmemb))
    {
      set_errno (ENOMEM);
      return NULL;
    }

  /* allocate memory */
  ptr = malloc (size);

  /* get pointer to info part of chunk */
  info = __mem2info (ptr);

  /* fill memory with zeros and set __MEM_CALLOC flag */
  memset (ptr, 0, info->size);
  info->flags |= __MEM_CALLOC;

  return ptr;                   /* happy end */
}
于 2010-11-03T03:06:28.510 回答
0

唯一显着的区别是calloc需要将分配的空间初始化为零,而malloc. 否则,我想只是出于历史原因,有两个不同的功能。

于 2010-11-03T03:07:21.647 回答
0

Everything is just bytes 是一个相对较新(即 c/Unix 时代)的发明——在许多其他架构上,都是固定大小的记录。

于 2010-11-03T03:07:34.467 回答