calloc的两个参数

san*_*oyd 27 c calloc

为什么要calloc采用两个参数而不是一个malloc

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

calloc (a, b);
calloc (b, a);
calloc (a * b, 1);
calloc (1, a * b);
Run Code Online (Sandbox Code Playgroud)

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

AnT*_*AnT 9

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

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

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

我一直认为第一个解释是正确的.但是,在阅读了这里的一些帖子后,我有疑虑.

  • @Svisstack:这正是我在标准中看到的,我认为AndreyT提出了一个有趣的观点.`size_t`定义为`sizeof`返回的类型.*实际上不是*作为对象的最大大小.有些对象不能应用`sizeof`,特别是动态分配的数组.我不认为标准中出现"系统边界"这个短语.如果你想证明标准中实际禁止(2)中描述的设置,我认为你必须做得比"它在我的64位系统上失败"做得更好. (3认同)
  • @Svisstack:我在谈论C标准.当我谈到标准的标准和特定实现之间的区别时,我真的知道我在说什么.这根本不是关于我如何"想要"`calloc`的实现 - 如果AndreT提出的奇怪的东西被标准禁止,我更喜欢它.我只是不知道它在哪里.如果您所说的只是AndreyT的选项(2)不适用于您的PC,那么做得好,您是对的.但问题是关于C标准的基本原理,而不是关于你的PC. (3认同)
  • -1,从技术上讲,你不能在`size_t`中分配更多相等和大于最大值,因为它是系统边界,而在其他方面,这没有任何意义.在32位计算机上,您将尝试分配所有可能的地址空间,这是不可能的,在64位计算机上也会失败. (2认同)
  • @Svisstack C标准从未说它只适用于标准机器,有人可以为他们的超级计算机中心编写一个C编译器,其中非常大的内存分配实际上是有意义的. (2认同)

sup*_*cat 6

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


Svi*_*ack 2

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 */
}
Run Code Online (Sandbox Code Playgroud)

  • *此函数仅用于以漂亮的方式传递元素的大小和元素的数量,在 malloc 中时,您必须乘以这些值才能获得所需的字节数。* -> 那么为什么我们没有一个与 `malloc` 类似的接口? (2认同)