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

C语言解析S-expression时结构体内部void*指针转换与打印问题

核心问题

你的故障和void*语法本身无关,主要存在三类错误:

  • 非法引用栈内存:函数内定义的局部变量(temp数组、tmp整型)都存在栈空间,函数执行结束后栈会被回收,你直接把这些局部变量的地址赋值给blob,后续访问这些地址属于未定义行为,是乱码、无输出的核心原因
  • 打印函数逻辑错误:switch分支没有加break,匹配后会顺序执行后续所有分支代码;同时格式化符和传入参数类型不匹配,void*需要先转换为对应类型的指针再解引用才能正常取值
  • 内存操作逻辑错误:字符串解析分支中你给current->blob申请了堆内存后,又直接把栈地址赋值给blob,既造成内存泄漏,又回到了栈引用的问题,没有做实际的字符串拷贝

修复代码

修正parse_term函数

atom* parse_term(char* str) {
    atom* current = malloc(sizeof(atom));
    // 初始化避免野指针
    current->blob = NULL;
    current->type = -1;
    
    if(str[0] == '\'') {
        // letter类型存储单个字符,需要在堆上申请char大小的空间
        char* letter_val = malloc(sizeof(char));
        *letter_val = str[1];
        current->blob = letter_val;
        current->type = letter;
    } else if(str[0] == '"') {
        char temp[256] = {0};
        int pos = 0;
        int str_pos = 1;
        while(str[str_pos] != '"' && str_pos < 255) {
            temp[pos++] = str[str_pos++];
        }
        // 申请对应长度的堆内存,+1给字符串结束符
        char* str_val = malloc((pos + 1) * sizeof(char));
        strcpy(str_val, temp);
        current->blob = str_val;
        current->type = string;
    } else if(isdigit(str[0])){
        char temp[256] = {0};
        int pos = 0;
        while(str[pos] != ' ' && str[pos] != '\0' && pos < 255) {
            temp[pos++] = str[pos];
        }
        // 整型单独申请堆空间存值
        int* int_val = malloc(sizeof(int));
        *int_val = atoi(temp);
        current->blob = int_val;
        current->type = integer;
    }
    return current;
}

修正print_atom函数

void print_atom(atom* current) {
    if(current == NULL || current->blob == NULL) return;
    switch(current->type) {
        case string:
            printf("atom: %s\ttype: %d\n", (char*)current->blob, current->type);
            break;
        case letter:
            printf("atom: %c\ttype: %d\n", *(char*)current->blob, current->type);
            break;
        case integer:
            printf("atom: %d\ttype: %d\n", *(int*)current->blob, current->type);
            break;
        default:
            printf("unknown atom type\n");
    }
}

可选优化方案

你提到的在结构体中单独定义所有类型变量确实会浪费空间,更推荐用C语言的联合体实现,既节省空间,也比void*更安全,不需要手动处理内存类型对应关系,示例定义如下:

typedef struct {
    union {
        char letter_val;
        int int_val;
        char* str_val;
    } value;
    atom_type type;
} atom;

内容的提问来源于stack exchange,提问作者Bithov Vinu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 04:15:08