为什么有些POSIX函数会获得元素编号和元素大小参数?

请参阅: http : //pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html

malloc函数只是获取要分配的数组大小。

但是: http : //pubs.opengroup.org/onlinepubs/009695399/functions/calloc.html

并且: http : //pubs.opengroup.org/onlinepubs/009695399/functions/fread.html

只是两个接收元素大小和元素数量的函数示例。

为什么会有这种差异? 获得尺寸不是更简单吗?

这更像是一个注释而不是一个原因,但是就fread(3)fwrite(3)的返回值而言, sizenmemb的值确实有所不同。 它们返回读取或写入的元素数,其中每个元素的sizesize参数确定。

POSIX还说了以下几点。 fread()

如果读取了部分元素,则其值未指定。

,因此理论上,当读取的数据量不是size的倍数时(由于文件结束或错误), size的值也会对您获得的数据产生影响。

对于calloc() ,GNU C库(glibc)简单地将sizenmemb放在一起,同时检查溢出(使用技巧快速检测大多数不会溢出的sizenmemb对)。 这是来自glibc 2.20的相关代码(来自malloc / malloc.c中的 __libc_calloc()nmembsize分别称为nelem_size 。):

  /* size_t is unsigned so the behavior on overflow is defined. */ bytes = n * elem_size; #define HALF_INTERNAL_SIZE_T \ (((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2)) if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0)) { if (elem_size != 0 && bytes / elem_size != n) { __set_errno (ENOMEM); return 0; } } 

之后从未引用过nelem_size 。 而是使用bytes

fread()实现( libio / iofread.c中的 _IO_fread() )类似地将nmembsize放在一起,并且仅使用它们来计算之后的返回值。 (与calloc()不同,它不检查溢出。)

我猜测有两个参数可能是历史的原因。 我也会对答案感兴趣。 也许size参数在fread()fwrite()某个点指定了每个I / O操作的块大小(或作为提示fwrite()

更新 : 这个答案和评论有一些有趣的讨论。 calloc()

我认为在callocfread函数中需要将值放在数组的元素中,所以如果它一次性放置它们必须逐个放置这可能会导致问题,因为你的cpu可能在[little-endian]中( http:// en.wikipedia.org/wiki/Endianness )订单。
例如,如果要在little-endian机器中将四个元素设置为1:

元素大小= 2字节:
| 01 00 | 01 00 | 01 00 | 00 01 |
元素大小= 3字节:
| 01 00 00 | 01 00 00 | 01 00 00 | 01 00 00 |

而对于fread ,这是基于如何实施fread。 单UNIX规范说

对于每个对象,应对fgetc()函数进行大小调用,并按顺序读取存储在unsigned char数组中的结果,该数组与对象完全重叠。