代碼中連續兩次調用 show_all(head),第二次仍能正常打印所有節點數據。疑問:show_all 內部將 head 指針移動至鏈表末尾(NULL),為何第二次調用不受影響?
void show_all(st* head) { // 參數是指針的副本
while (head != NULL) {
printf("%d,%f\n", head->num, head->score);
head = head->pnext; // 修改的是副本,不影響實參
}
}
main 中的 head 指針,指向鏈表頭節點。show_all 的 head 參數,是實參的拷貝(同樣指向頭節點)。head 指向下一節點,實參 main::head 保持不變,仍指向頭節點。main() 棧幀: show_all() 棧幀 (第 1 次調用):
head ──────┐ head ──────┐
│ │
▼ ▼
[節點 1] → [節點 2] → ... → [節點 5] → NULL
(堆內存,雙方共享)
第二次調用時,形參再次獲得實參的拷貝(仍指向頭節點),遍歷邏輯完全獨立。
原代碼存在語法錯誤(缺少 *、頭文件不全),修正版:
#include <stdio.h>
#include <stdlib.h>
struct student {
int num;
float score;
struct student *pnext;
};
typedef struct student st;
void add(st **phead, int inum, float iscore) {
st *newnode = (st*)malloc(sizeof(st));
newnode->num = inum;
newnode->score = iscore;
newnode->pnext = NULL;
if (*phead == NULL) {
*phead = newnode;
} else {
st *p = *phead;
while (p->pnext != NULL) p = p->pnext;
p->pnext = newnode;
}
}
void show_all(st *head) { // 值傳遞:接收指針副本
while (head != NULL) {
printf("%d, %.2f\n", head->num, head->score);
head = head->pnext; // 僅移動局部副本
}
}
int main() {
st *head = NULL;
add(&head, 1, 20.0);
add(&head, 2, 30.0);
add(&head, 3, 40.0);
add(&head, 4, 50.0);
add(&head, 5, 60.0);
show_all(head); // 第一次遍歷
printf("---\n");
show_all(head); // 第二次遍歷,head 仍指向頭節點
return 0;
}
若函數需要修改實參指針(如刪除頭節點),必須傳遞指針的指針或引用:
// C 風格:二級指針
void delete_head(st **phead) {
if (*phead) {
st *tmp = *phead;
*phead = (*phead)->pnext; // 修改實參指向
free(tmp);
}
}
// C++ 風格:引用
void delete_head(st *&head) {
if (head) {
st *tmp = head;
head = head->pnext;
delete tmp;
}
}
show_all 等只讀遍歷函數的安全性與可重入性。