C语言指针实现栈反转:原栈被意外修改的问题排查
问题核心分析
你的reverseStack函数在反转过程中直接销毁了原栈的所有节点,这是导致后续原栈“被意外修改”的根本原因。
具体来说,你在reverseStack里调用了pop(¤tPtr),而pop函数的逻辑是:取出节点数据后,直接free掉该节点。虽然currentPtr是原栈top指针的副本,但它指向的是原栈的实际节点——执行pop后,原栈的节点会被逐个释放,原栈的top指针会变成悬空指针(指向已释放的内存)。后续再操作原栈时,访问的是已失效的内存,从而引发未定义行为(表现为原栈数据异常、程序崩溃等)。
解决方案(根据需求二选一)
方案1:保留原栈,生成独立的反转新栈
如果你需要保留原栈的完整数据,同时得到一个反转的新栈,不要用pop销毁原节点,而是遍历原栈复制数据到新栈:
StackNodePtr reverseStack(StackNodePtr currentPtr) { StackNodePtr newPtr = NULL; // 仅遍历原栈复制数据,不修改、不释放原节点 while (currentPtr != NULL) { push(&newPtr, currentPtr->data); currentPtr = currentPtr->nextPtr; } return newPtr; }
这种方式下,原栈和反转后的新栈完全独立,互相不会影响。
方案2:原地反转原栈(无额外内存开销)
如果你不需要保留原栈,希望直接修改原栈的指针实现反转(更高效),可以用链表原地反转的逻辑,避免malloc和free操作:
StackNodePtr reverseStack(StackNodePtr topPtr) { StackNodePtr prev = NULL; StackNodePtr curr = topPtr; StackNodePtr next = NULL; while (curr != NULL) { next = curr->nextPtr; // 保存下一个节点的指针 curr->nextPtr = prev; // 反转当前节点的指向 prev = curr; // 更新prev为当前节点 curr = next; // 移动到下一个节点 } // prev现在是反转后的栈顶指针 return prev; }
调用时直接用原栈的top指针接收返回值即可:
originalTop = reverseStack(originalTop);
额外健壮性优化
你的pop函数未处理栈为空的情况,当栈空时(*topPtr)->data会触发空指针解引用,导致程序崩溃。建议增加空栈检查:
BizarreNumber_t pop(StackNodePtr *topPtr) { if (*topPtr == NULL) { fprintf(stderr, "Error: Pop from empty stack!\n"); exit(EXIT_FAILURE); // 也可以返回一个标记性的BizarreNumber_t值 } StackNodePtr tmpPtr = *topPtr; BizarreNumber_t result = tmpPtr->data; *topPtr = tmpPtr->nextPtr; free(tmpPtr); return result; }
内容的提问来源于stack exchange,提问作者trtrtz
相关产品推荐
相关产品推荐

