有人可以帮我理解使用链表的void指针。
我有:
struct listNode
{
int nodeValue;
struct listNode * next;
};
typedef struct listNode listNode;
仅适用于整数。如果我将int nodeValue更改为void * nodeValue,我将如何使用void指针将值发送到链接列表中?
例如,我有一个添加到前面的功能:
void addFront(listNode *L, int number);
采用listNode和数字。
如果它是一个void *指针,我只需将签名更改为:
void addFront(listNode *L, void* value);
在使用整数的主函数中,我有类似的东西:
int main(void)
{
listNode *list;
list = createList();
for (int x = 0;x < 8;x++)
{
addFront(list,x);
}
return(0);
}
其中createList定义为:
listNode *createList()
{
listNode *anyNode;
anyNode = malloc(sizeof(listNode));
anyNode->next = NULL;
return anyNode;
}
listNode *initNode(int number)
{
listNode *newNode;
newNode = malloc(sizeof(listNode));
newNode->nodeValue = number;
newNode->next = NULL;
return(newNode);
}
为了使列表更通用,我如何使用void *传递整数而不是声明整数。
答案 0 :(得分:1)
不幸的是,这种通用行为的代价是开销很大:为了在列表上保存int
,您需要通过动态分配int
来扩展其范围:
listNode *initNode(int number)
{
listNode *newNode;
newNode = malloc(sizeof(listNode));
newNode->nodeValue = malloc(sizeof(int));
*(newNode->nodeValue) = number;
newNode->next = NULL;
return(newNode);
}
这会多次增加内存需求,因为malloc(sizeof(int));
通常至少分配一个16字节的块。
答案 1 :(得分:0)
存储int或指针的一种方法是将nodeValue转换为union类型。请注意,为了避免未定义的行为,您的调用代码需要保持一致(即,如果您在链表中添加int,则不应尝试以后将它们作为指针访问,反之亦然)。
union intOrPointer
{
int intValue;
void * pointerValue;
};
struct listNode
{
union intOrPointer nodeValue;
struct listNode * next;
};
typedef struct listNode listNode;
listNode *initNode(int number)
{
listNode *newNode;
newNode = malloc(sizeof(listNode));
newNode->nodeValue.intValue = number;
newNode->next = NULL;
return(newNode);
}
答案 2 :(得分:-1)
替代解决方案是将0-size数组用于listNode声明。 例如:
#include <stdlib.h>
#include <string.h>
struct listNode
{
struct listNode *next;
int nodeValue[0];
};
struct listNode *addFront(struct listNode **head, void *data, size_t size)
{
struct listNode *new_node = calloc(sizeof(struct listNode) + size, 1);
if(!new_node)
return NULL;
new_node->next = *head;
*head = new_node->next;
memcpy(new_node->nodeValue, data, size);
}
void addInt2Front(struct listNode **head, int value)
{
addFront(head, &value, sizeof(value));
}
int main(void)
{
struct listNode *head = NULL;
addInt2Front(&head, 5);
}
它减少了两次分配的开销,因为nodeValue的内存通过一次calloc()调用分配了listNode块。