更新指针值会影响此前赋值吗?指针与动态链表技术问询
问题分析与解决:链表节点复用导致的指针错误
让我来帮你拆解一下这个问题——你遇到的核心问题是重复使用了同一个tmp_edge指针实例,没有为每次循环的新边节点分配独立内存,最终导致链表构建逻辑完全偏离预期。
为什么会出现这个问题?
咱们看你的代码:你只在循环外面执行了一次tmp_edge = malloc(sizeof(graph_edge_t)),之后的每一轮循环,你都是在修改这个同一个节点的内容,然后把last_edge指向它。
举个具体的执行流程:
- 第一次循环:给
tmp_edge的adjac_vertex_p赋值为2,tmp_edge->next_edge_p = last_edge(此时last_edge是NULL),接着把last_edge指向tmp_edge。 - 第二次循环:直接覆盖
tmp_edge->adjac_vertex_p的值为3,然后执行tmp_edge->next_edge_p = last_edge——但此时last_edge已经指向了这个唯一的tmp_edge节点,相当于让这个节点的next_edge_p指向了自己! - 后续循环重复这个逻辑,所有的“节点”其实都是同一个内存地址的实例,所以打印时
last_edge和tmp_edge的内容完全一致,自然输出不符合预期。
怎么解决?
核心思路是:每次循环都要为新的graph_edge_t节点分配独立的内存,不能复用同一个指针。修改后的代码如下:
#include <stdio.h> #include <stdlib.h> /* Structure used to hold a graph vertex information. */ typedef struct graph_vertex { int identifier; struct graph_vertex *next_vertex_p; struct graph_edge *edge_list_p; } graph_vertex_t; /* Structure used to hold a graph edge information. */ typedef struct graph_edge { struct graph_vertex *adjac_vertex_p; struct graph_edge *next_edge_p; } graph_edge_t; int main (int argc, char *argv[]) { graph_edge_t *tmp_edge = NULL; graph_edge_t *last_edge = NULL; int id_conn[4] = {2,3,4,5}; for (int i = 0; i < 4; i++) { // 关键修改:每次循环创建全新的边节点 tmp_edge = (graph_edge_t *)malloc(sizeof(graph_edge_t)); printf("%d ", id_conn[i]); tmp_edge->adjac_vertex_p = malloc(sizeof(graph_vertex_t)); tmp_edge->adjac_vertex_p->identifier = id_conn[i]; tmp_edge->next_edge_p = last_edge; // 此时last_edge是上一轮的节点,初始为NULL if(tmp_edge->next_edge_p != NULL) { printf("LE: %d : TMP %d : EDGE: %d \n", last_edge->adjac_vertex_p->identifier, tmp_edge->adjac_vertex_p->identifier, tmp_edge->next_edge_p->adjac_vertex_p->identifier); } last_edge = tmp_edge; // 更新last_edge为当前新节点 } // 别忘了释放内存,避免泄漏 graph_edge_t *temp_free; while(last_edge != NULL) { temp_free = last_edge; free(last_edge->adjac_vertex_p); last_edge = last_edge->next_edge_p; free(temp_free); } return 0; }
关键修改点说明
- 把
tmp_edge = malloc(...)移到了循环内部,确保每一轮循环都生成一个独立的graph_edge_t节点,每个节点都有自己的内存空间。 - 现在执行
tmp_edge->next_edge_p = last_edge时,last_edge保存的是上一轮循环创建的节点(第一次循环时是NULL),不会出现自引用的情况。 - 新增了内存释放逻辑,这是C语言编程里的好习惯,避免程序结束后留下内存泄漏。
预期输出验证
修改后运行代码,你会得到完全符合预期的输出:
2 3 LE: 2 : TMP 3 : EDGE: 3 4 LE: 3 : TMP 4 : EDGE: 4 5 LE: 4 : TMP 5 : EDGE: 5
内容的提问来源于stack exchange,提问作者BRHSM
相关产品推荐
相关产品推荐

