iovec 的 iov_len 字段是否定义明确?

问题描述

根据Pointer arithmetic for void pointer in C,不允许使用空指针进行算术运算。然而,iovec 结构看起来像这样:

struct iovec {
    void *iov_base;
    size_t iov_len;
};

这是在POSIX standard中定义的,iov_len字段被描述为有点模糊的“iov_base指向的内存大小”。由于 iovec 只是一个数据结构,我想知道接受它作为输入参数的函数是否定义了它们如何使用 iov_len 字段,但是 readvwritev 都描述了它,再次模糊地,作为“内存区域的长度。”

对于某些函数iov_len 字段的含义似乎是明确定义的。例如,recvmsg 规范说“iov_len 字段以字节为单位给出 [存储区域的] 大小”。此外,recv 接受空指针和长度,正确地将长度参数定义为缓冲区的长度(以字节为单位)。

我的问题:在这些被定义为缓冲区长度的情况下,iov_len 字段的含义是否明确定义?

解决方法

我相信你只是在这里想多了。这里的“大小”绝对是指“以字节为单位的大小”,在您提到的情况下,我认为“大小”和“长度”这两个词之间没有任何有意义的区别。您没有遗漏任何细微之处。

他们没有像在许多其他地方那样说“以字节为单位”可能有点草率,如果您真的愿意,您可以提交缺陷报告,但我认为没有太多混淆的余地因为真的没有其他合理的解释。

没有人声称 void 有大小,但使用 void * 作为指向大小以字节为单位的通用缓冲区的指针是很常见的;使用 void * 而不是 unsigned char * 可以方便地将指针传递给其他类型而无需强制转换。

,

处理 void * 和显式大小是很常见的。它允许您忘记所引用的对象类型,从而重用相同的 void * 字段来存储不同类型的数据,而无需使用 union

需要 size 的原因通常是 memcpy,它复制连续内存。这样,您不仅可以将数据保存在 void * 中(您知道所需的大小,因此您可以安全地malloc),还可以将其传递。

当然,您始终可以通过将 void * 转换为其他类型(例如 size_t *)来返回到类型化世界。


void * 通常用于在 C 中实现“通用”数据结构或用于高阶函数。例如这里是 qsort 定义:

void qsort(
   void *base,size_t number,size_t width,int (__cdecl *compare )(const void *,const void *)
);