首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言指針與鏈表經典例題全解析:malloc/calloc/realloc/free 與鏈表增刪查

     編輯:關於C語言

動態內存管理四大函數

函數用途關鍵差異
malloc(size)分配未初始化內存內容隨機,需手動清零
calloc(n, size)分配並歸零等價 malloc + memset(0)
realloc(ptr, new_size)調整已分配塊大小可能移動地址,必須用返回值更新指針
free(ptr)釋放內存釋放後指針成野指針,建議置 NULL

代碼示例速覽

// 10.1 malloc
int *p = (int *)malloc(sizeof(int));
*p = 100; printf("%d\n", *p); free(p);

// 10.2 calloc 分配字符數組
char *ch1 = (char *)calloc(26, sizeof(char)); // 自動歸零
char *ch2 = (char *)malloc(26);
for (int i=0;i<26;i++) { ch1[i]=65+i; ch2[i]=97+i; } // 大小寫字母

// 10.3 realloc 擴容/縮容
double *f = (double *)malloc(sizeof(double));
short *s = (short *)realloc(f, sizeof(short)); // 必須接收返回值!

// 10.4 free 釋放後訪問是未定義行為
int *pInt = (int *)malloc(sizeof(int));
*pInt = 100; free(pInt); printf("%d\n", *pInt); // 輸出不可預期

鏈表核心操作三部曲

1. 創建並輸出(例 10.5)

struct Student { char cName[20]; int iNumber; struct Student *next; };
struct Student *Create() {
    struct Student *pHead=NULL, *pEnd, *pNew;
    pEnd = pNew = (struct Student *)malloc(sizeof(struct Student));
    scanf("%s%d", pNew->cName, &pNew->iNumber);
    while (pNew->iNumber != 0) {
        if (pHead==NULL) { pNew->next=pHead; pHead=pNew; }
        else { pNew->next=NULL; pEnd->next=pNew; pEnd=pNew; }
        pNew = (struct Student *)malloc(sizeof(struct Student));
        scanf("%s%d", pNew->cName, &pNew->iNumber);
    }
    free(pNew); return pHead; // 釋放最後多分配的節點
}

2. 頭插法插入(例 10.6)

struct Student *Insert(struct Student *pHead) {
    struct Student *pNew = (struct Student *)malloc(sizeof(struct Student));
    scanf("%s%d", pNew->cName, &pNew->iNumber);
    pNew->next = pHead;  // 新節點指向原頭
    return pNew;         // 新節點成為新頭
}

3. 按序號刪除(例 10.7)

void Delete(struct Student *pHead, int iIndex) {
    struct Student *pTemp = pHead, *pPre = pHead;
    for (int i=1; inext; }
    pPre->next = pTemp->next;  // 旁路被刪節點
    free(pTemp);               // 釋放內存
}

4. 兩有序鏈表合併(例 10.8)

void merge(struct Student *La, struct Student *Lb) {
    struct Student *a=La->next, *b=Lb->next, *c=La;
    while (a && b) {
        if (a->iNumber <= b->iNumber) { c->next=a; c=a; a=a->next; }
        else { c->next=b; c=b; b=b->next; }
    }
    c->next = a ? a : b;  // 尾部拼接
    free(Lb);             // 釋放 Lb 頭節點
}

高頻錯誤避坑指南

  1. malloc 未判空 → 分配失敗直接解引用崩潰
  2. realloc 直接覆蓋原指針 → p = realloc(p, ...) 若失敗返回 NULL,原內存洩漏;正確寫法 void *tmp = realloc(p, ...); if (tmp) p = tmp;
  3. free 後不置 NULL → 野指針二次 free 或誤用
  4. 鏈表遍歷修改 next 指針順序錯 → 先保存 next 再 free
  5. scanf 格式串 %s 不限長度 → 緩衝區溢出,用 %19s

練習建議

  • 手寫「雙向鏈表反轉」「單鏈表找中點」「檢測環」
  • Valgrind 檢測內存洩漏:valgrind --leak-check=full ./a.out
  • 閱讀 Linux 內核 list_head 實現,理解無侵入式鏈表設計
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved