在C函数中,为什么需要"nmem"和"size"参数?

8

可能重复:
C语言中malloc和calloc的区别
为什么calloc需要两个参数而malloc只需要一个参数?

我注意到许多C函数调用尤其是涉及内存或文件操作的函数调用,并不都使用两个参数。例如,malloc只传递一个参数,即所需内存空间的字节数。另一方面,calloc传递了两个参数,即元素大小(size)和元素数量(nmem)。还有其他使用这些size和nmem参数的函数。

从本质上讲,calloc调用将分配与调用malloc(nmemsize)相同的内存量,因此实际上发生的是将星号()替换为逗号(,)。至少在我工作的较高层次上,我看不出调用calloc(1, nmemsize)、calloc(nmemsize, 1)或calloc(nmem, size)之间的区别。

在更低层面上是否有实际发生的事情,使得例如calloc(1, nmem*size)和calloc(nmem, size)之间存在根本性差异?

编辑:我知道calloc和malloc之间的功能区别。我感兴趣的是参数之间的差异。还有其他使用2个大小参数作为总大小的函数(如fread,fwrite等)。我关心的不是具体的函数,而是为什么在函数中有两个用于总大小的参数,当实质上总大小变成这两个参数相乘时。大多数情况下,我使用需要的“size”参数和“nmem”(有时是“count”等)参数的“1”。


1
使用两个参数形式可以提高内存对齐(在需要的平台上)。 - wallyk
关于malloc()calloc(),您可以在这里找到有趣的差异解释:https://dev59.com/1XI_5IYBdhLWcg3wEexu#1585987 ...无论如何,您能否指出您考虑的除后两个函数之外的其他函数。 - alk
2
@Paciv 这并不完全是重复的问题,因为那个问题及其答案没有涉及参数数量的差异。 - Dave Rager
2
@wallyk,我对有关对齐问题的更多信息很感兴趣,能否在回答中解释一下? - Dave Rager
@JensGustedt 我同意关于重复的观点。那个问题上被接受的答案在评论中有一个非常有趣的讨论。 - Dave Rager
@JensGustedt 谢谢。该线程中的讨论仅考虑了malloc和calloc之间的差异。似乎参数差异的原因是历史性的,因为内存大小要小得多,可能是由于不同的开发人员。我认为对于其他使用2个大小参数而不是1个的函数也是如此,但也许这取决于函数。 - Chris
2个回答

2
在对该问题的评论中,我写道 calloc()允许更好地内存对齐,适用于有关紧密度的平台。 我还没有找到任何支持这一点的东西(但是我相信这是VMS / VAXC编译器的一个功能,但是相关资源很少)。

然而,我发现在1975年5月Unix V6发布时 calloc()和alloc()同时出现。 在11个月前发布的V5中,两个函数都不存在; 内核和运行时库(以及汇编程序和C编译器)都是用汇编语言编写的。
在V6版本中,实现了calloc,它是一个仅有四行源代码的模块。
calloc(n, s)
{
return(alloc(n*s));
}

calloc()不会清空分配的内存;请参见alloc(),在V6中没有calloc()man页面;然而alloc()的man页面如下:

描述
Allocfree提供了一个简单的通用内核管理包。 Alloc给出一个字节大小;它返回一个指向至少该大小的区域的指针, 这个区域是偶数的,因此可以容纳任何类型的对象。 free的参数是以前由alloc分配的区域的指针;这个空间可供进一步分配使用。

不用说,如果alloc分配的空间被超越或者一些随机数被传递给free,将会导致严重的混乱。

该例程使用一种首次适配算法,该算法将正在释放的块与其他已经释放的块合并起来。 当没有合适的空间可用时,它调用sbrk(参见"break(II)")从系统中获取更多内核。

诊断
如果没有可用的内核,则返回-1

错误
分配的内存包含垃圾而不是被清除。

甚至在内存耗尽的情况下也不会返回NULL

calloc()首次正式出现在UNIX V7中,即1979年1月,同时出现了其他几个改进

  • calloc()清空返回的内存。
  • alloc()更名为malloc()
  • realloc()出现了
  • 在内存不足或堆错误的情况下,函数“返回一个空指针(0)”

抱歉如果我漏掉了什么,但这个回答如何解决问题?从代码中我只看到calloc只是调用alloc,但它为您执行乘法。结论是它只是一种美好的东西还是开发人员随意实现的随机细节? - kurtzbot

0
调用 calloc(1, nmem*size) 和 calloc(nmem, size) 之间是否存在实际发生在较低级别的某些事情,使它们不同?由于 calloc() 填充了零内存,理由可能是它可能会浪费更多的周期去进行 mult。相比之下,malloc() 获得了使用预先计算值的机会,可能会减少调用中的开销,从而使其更容易满足。别忘了 C 语言是在 CPU 每个周期成本很高的时代设计的,因此与许多其他“高级”语言相比,设计非常精简。这个问题可能最好由 C 的作者丹尼斯·里奇来回答。

Dennis Ritchie暂时不会回答任何问题,除非通过ouija板... - Donal Fellows

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接