如何通过void指针访问结构体字段?C语言Node节点存储自定义结构体的指针访问异常问题
问题诊断与修复方案
嘿,你这是踩了个指针使用的经典小坑——数据检索的逻辑完全错了,咱们一步步把问题拆解开:
核心问题:错误的指针转换
看你取出数据的这行代码:
struct Test *new_test = (struct Test *)&node->data;
这里的node->data本身就是一个void*指针,指向你用malloc分配的、已经拷贝了test结构体数据的堆内存区域。但你现在取的是node->data这个指针变量自身的地址,而不是它指向的实际数据地址!
这就导致new_test指向的是Node结构体里data成员的内存位置(而不是存储Test数据的堆内存),读出来的自然是无意义的随机值。
修复方法
直接把node->data转换成struct Test*即可,不需要取地址:
struct Test *new_test = (struct Test *)node->data;
之后你就可以正常访问结构体成员了,打印代码也能简化:
printf("%d\n", new_test->value); // 正常输出200 printf("%s\n", new_test->key); // 正常输出"test"
额外优化建议:构造函数的改进
你的node_constructor返回栈上的Node实例,再赋值给堆上的节点,这个写法本身没问题,但更符合链表开发习惯的是直接返回堆分配的节点指针,还能避免栈变量的潜在风险,同时增加内存分配失败的检查:
struct Node* node_constructor(void *data, unsigned long size) { // 先为Node本身分配内存 struct Node *node = malloc(sizeof(struct Node)); if (!node) return NULL; // 检查malloc是否成功 // 为数据分配内存 node->data = malloc(size); if (!node->data) { free(node); // 数据分配失败时,要释放已分配的Node内存,避免内存泄漏 return NULL; } memcpy(node->data, data, size); node->next = NULL; node->prev = NULL; return node; }
使用这个构造函数时,main函数里的代码可以简化成:
struct Node *node = node_constructor(&test, sizeof(test)); if (!node) { // 处理内存分配失败的情况 return 1; }
注意事项:字符串指针的拷贝风险
你的Test结构体里的key是字符串字面量的指针,拷贝结构体时只会拷贝指针值,而不是字符串的实际内容。如果之后这个字符串的内存被释放或修改,new_test->key就会变成野指针。如果需要存储动态管理的字符串,你需要在构造函数里单独为key分配内存并拷贝字符串内容,比如:
// 假设你要存储的Test结构体是动态字符串 struct Test { int value; char *key; }; // 对应的构造逻辑(需要额外处理key) struct Node* node_constructor_test(struct Test *test_data) { struct Node *node = malloc(sizeof(struct Node)); if (!node) return NULL; struct Test *copied_test = malloc(sizeof(struct Test)); if (!copied_test) { free(node); return NULL; } copied_test->value = test_data->value; // 为字符串分配内存并拷贝 copied_test->key = malloc(strlen(test_data->key) + 1); if (!copied_test->key) { free(copied_test); free(node); return NULL; } strcpy(copied_test->key, test_data->key); node->data = copied_test; node->next = NULL; node->prev = NULL; return node; }
内容的提问来源于stack exchange,提问作者Daniel Tanase
相关产品推荐
相关产品推荐

