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

结构体char指针在void函数赋值后main函数打印出现乱码

问题描述

我用typedef定义了名为Node的结构体,其中key成员是char类型指针,用于动态赋值。头文件cnode.h代码如下:

#include <stdio.h>

typedef struct Node {
    char *key;
    int value;
    Node *next = NULL;
    
} Node;

void print_node(Node x){
    printf("[%s, %d]\n",x.key, x.value);
    
}

void print_list(Node head){
    printf("\n");
    while (head.next !=NULL){
        print_node(head);
        head = *head.next;
        printf("-->");
    }
    print_node(head);
}

我将Node声明为set[CAPACITY]数组,试图实现近似O(1)访问的集合结构,通过哈希函数计算插入位置,在外部void insert()函数中完成插入操作。为验证正确性,我在insert()和main()函数中均打印key值,但结果不一致。主程序代码如下:

#include <stdio.h>
#include "cnode.h"

#define CAPACITY 50

unsigned long hash_function(int x)
{
    unsigned long i;
    i = x*(x+3)+x; //Knuth Variant on Division
    return i % CAPACITY;
}

void insert(Node *set, int value){
    char key[20];
 
    sprintf(key, "%d", value);

    int loc = hash_function(value);
    
    set[loc].key = key;
    set[loc].value = value;
 
    print_node(set[loc]);
}

int main(){
    Node set[CAPACITY];

    insert(set, 18);
    insert(set, 122);
    
    printf("\nVALIDATION\n");
    print_node(set[46]);
    print_node(set[22]);
}

使用g++编译命令:

g++ -o main main.c && ./main 

输出结果:

[18, 18]
[122, 122]

VALIDATION
[�7�H�, 18]
[�7�H�, 122]

尝试了多种指针和地址操作仍无法解决乱码问题,请问忽略了什么?


问题原因与解决方案

核心问题:栈内存的生命周期

你在insert()函数中定义的char key[20]是栈上的局部数组,函数执行完毕后,当前函数的栈帧会被销毁,这块内存会被操作系统回收或重新分配给其他操作使用。当你把key的地址赋值给set[loc].key时,这个指针在insert()函数内是有效的(因为函数还在执行),所以打印正常;但回到main()函数后,这个指针指向的内存已经无效,访问它就会读取到随机的垃圾数据,也就是你看到的乱码。

解决方案:使用动态分配的堆内存

要解决这个问题,需要为key分配堆内存,堆内存的生命周期不受函数栈帧影响,直到你主动释放它。修改insert()函数如下:

#include <stdlib.h> // 需要引入stdlib.h来使用malloc和free

void insert(Node *set, int value){
    char *key = malloc(20 * sizeof(char)); // 动态分配20字节的内存
    if (key == NULL) { // 检查内存分配是否成功
        perror("malloc failed");
        return;
    }
    sprintf(key, "%d", value);

    int loc = hash_function(value);
    
    // 如果该位置之前已经有key,先释放旧内存避免泄漏
    if (set[loc].key != NULL) {
        free(set[loc].key);
    }
    set[loc].key = key;
    set[loc].value = value;
 
    print_node(set[loc]);
}

额外注意事项

  1. 内存泄漏:使用malloc分配的内存需要在不再使用时用free释放,比如程序结束前遍历整个set数组,释放每个非空的key指针。
  2. 结构体初始化:你的Node结构体中Node *next = NULL;是C++的写法,纯C语言不支持在结构体定义中直接初始化成员。如果后续要改用C编译器(比如gcc)编译,需要在创建Node实例时手动将next初始化为NULL,比如在main()中可以用循环初始化set数组:
    int main(){
        Node set[CAPACITY];
        // 初始化数组中的每个Node
        for (int i = 0; i < CAPACITY; i++) {
            set[i].key = NULL;
            set[i].value = 0;
            set[i].next = NULL;
        }
        // ... 后续代码
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:20:44