【问题标题】:How to typecast void to struct/union to access fields?如何将 void 类型转换为结构/联合以访问字段?
【发布时间】:2022-01-05 11:30:07
【问题描述】:

在尝试打印我创建的结构的字段时,我收到错误消息“成员引用基类型 'void' 不是结构或联合”。

这是通过单链表节点递增的 for 循环,只要该节点不为空:

for (NODE *temp = sList->head; temp!=NULL;temp=temp->next){
        printf("DocNo: %d \n",*(int)temp->dataPtr->docNum);
    }

我的NODE 结构如下所示(包含dataPtr 字段):

typedef struct node{ //node structure definition (the individual nodes in the list)
    void* dataPtr;
    struct node* next;
} NODE;

我的PRINTJOB 结构(包含docNum 字段):

typedef struct printJob{
    int docNum;
    int requestPri;
    int pageNums;
    int numCycles;
} PRINTJOB;

此外,我创建了一个指向PRINTJOB 结构的指针并用值填充字段,然后调用一个insertList() 函数,该函数接受一个指向已创建列表的指针和指向已填充PRINTJOB 结构的指针。

如何访问PRINTJOB的字段?

【问题讨论】:

  • 那么temp->dataPtr 是否真的指向struct printJob
  • 如果是这样,你想要printf("DocNo: %d\n", ((struct printJob *)temp->dataPtr)->docNum);
  • 是的,我相当肯定它确实如此,因为单步调试调试器表明链接被正确分配。当我打印出来时,它也会返回 struct printJob 的地址。
  • 结构的地址是它的第一个成员的地址。因此,每个列表节点的地址是struct printJob 的地址(例如指向)的地址。请注意上面@SteveSummit 如何在演员表和节点周围使用(...),以确保在访问docnum 成员之前具有正确的运算符优先级。跨度>

标签: c


【解决方案1】:

好的,temp 是指向NODE 的指针。所以temp->dataPtr 是一个指向void * 的指针。如果现在该数据实际上是指向 PRINTJOB 的指针,则需要将其告知编译器,因此您可以执行以下操作:

PRINTJOB * pj = (PRINTJOB *)temp->dataPtr;
int docNum = pj->docNum;

要在一行中完成这两件事,就像在代数中那样做;将pj 替换为第一行的定义,因此pj->docNum 变为:

(PRINTJOB *)temp->dataPtr->docNum

但是这里的问题是,解引用指针的优先级高于强制转换,所以编译器看到的其实是这样的:

(PRINTJOB *)(temp->dataPtr->docNum)

首先取消引用所有内容,然后强制转换。然而,这样你会尝试访问 void 指针 dataPtrdocNum,但这是行不通的。所以需要用括号来改变运算顺序:

((PRINTJOB *)temp->dataPtr)->docNum

现在编译器首先做一个 derference,然后是 cast,最后是另一个 derefence。无需强制转换为int,编译器知道PRINTJOBdocNumint 类型。

【讨论】:

    猜你喜欢
    • 2023-02-26
    • 2021-08-05
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多