You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 11:29:07