Why do some POSIX functions get a element number and element size parameters?

眉间皱痕 提交于 2020-01-14 14:26:07

问题


See: http://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html

The malloc function simply gets a array size to allocate.

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

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

Are just 2 examples of functions that receive element size and number of elements.

Why's that difference? Doesn't it more simple to get a size and that's it?


回答1:


This is more of a note than a reason, but the values of size and nmemb do make a difference as far as the return value of fread(3) and fwrite(3) is concerned. They return the number of elements read or written, where the size of each element is determined by the size parameter.

POSIX also says the following re. fread(),

If a partial element is read, its value is unspecified.

, so in theory the value of size could make a difference for the data you get back too when the amount of data read isn't a multiple of size (due to end-of-file or errors).

For calloc(), the GNU C library (glibc) simply multiplies size and nmemb together, also checking for overflow (using a trick to quickly detect most size and nmemb pairs that won't overflow). Here's the relevant code from glibc 2.20 (from __libc_calloc() in malloc/malloc.c. nmemb and size are called n and elem_size, respectively.):

  /* 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;
        }
    }

n and elem_size are never referenced after that. bytes is used instead.

The fread() implementation (_IO_fread() in libio/iofread.c) similarly multiplies nmemb and size together and only uses them to calculate the return value after that. (Unlike calloc(), it does not check for overflow.)

I'm guessing the reasons for having two parameters might be historical. I would be interested in the answer too. Perhaps the size parameter specified the block size of each I/O operation (or served as a hint) at some point for fread() and fwrite().

Update: This answer and the comments has some interesting discussion re. calloc().




回答2:


I think in calloc and fread functions want put values in array's elements so it must put them one by one if it put all of them at one time this may cause problem because your cpu may be in [little-endian] (http://en.wikipedia.org/wiki/Endianness) order.
for example if you want to set four element into 1 in little-endian machine:

element size = 2 bytes:
| 01 00 | 01 00 | 01 00 | 00 01 |
element size = 3 bytes:
| 01 00 00 | 01 00 00 | 01 00 00 | 01 00 00 |

and for fread, It's based on how fread is implemented. The Single UNIX Specification says

For each object, size calls shall be made to the fgetc() function and the results stored, in the order read, in an array of unsigned char exactly overlaying the object.



来源:https://stackoverflow.com/questions/29021191/why-do-some-posix-functions-get-a-element-number-and-element-size-parameters

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!