2

在 NetBSD 系统文件 usr/src/sys/sys/vnode.h 中定义了一个 vnode 的结构。但是,我看到有时在执行操作(比如说 ufs_getattr)时,vnode* 会作为 void* 传递给被调用的操作。

每个这样的操作都有其参数结构。例如,ufs_getattr() 的结构如下:

struct vop_getattr_args /* {
                struct vnode    *a_vp;
                struct vattr    *a_vap;
                kauth_cred_t    a_cred;
};

通常,这些操作的第一行执行将实际上是 void* 的 vnode 指针分配到此参数类型指针的指针中。例如,我们执行以下操作:

int
ufs_getattr(void *v)
{
        struct vop_getattr_args /* {
                struct vnode    *a_vp;
                struct vattr    *a_vap;
                kauth_cred_t    a_cred;
        } */ *ap = v;            //why this is okay to do ?
        struct vnode    *vp;
        struct inode    *ip;
        struct vattr    *vap;

        vp = ap->a_vp;           //wont this break ?

从 usr/src/sys/ufs/ufs/ufs_vnops.c 中提取

由于 C 编程知识很少,我无法证明这种不匹配的分配是正确的,因为类型并不真正匹配。

4

1 回答 1

4

在 C 中,将 a 分配void*给 aT*是合法的(在 C++ 中不是这样)。因此代码完全有效。

引用 K&R 的“The C Programming Language 2 nd Edition”:

任何指向对象的指针都可以转换为类型void *而不会丢失信息。如果将结果转换回原始指针类型,则恢复原始指针。与在 Par.A.6.6 中讨论的指针到指针转换通常需要显式转换不同,指针可以分配给类型指针和从指针分配void *,并且可以与它们进行比较。


作为一个有趣的旁注,关于void*(来自同一本书)的历史:

这种对void *指针的解释是新的;以前,char *指针扮演通用指针的角色。ANSI 标准特别祝福void *指针与对象指针在赋值和关系中的相遇,同时要求对其他指针混合进行显式强制转换。

于 2015-10-03T20:13:34.037 回答