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

C 語言經典面試題精析:字串操作與記憶體管理陷阱

     編輯:關於C語言

前言

C 語言看似簡單,實則暗藏眾多陷阱。本文整理七道經典面試題,涵蓋字串複製越界、陣列指標特性、動態記憶體管理、堆棧區別等核心考點,並提供健壯的修正方案。

題目一:strcpy 緩衝區溢出

void test1() {
    char string[10];
    char* str1 = "0123456789";
    strcpy(string, str1);
}

錯誤分析:源字串長度為 11(含結束符 \0),目標陣列僅 10 字節,導致緩衝區溢出。

健壯修正:

int StrCpy(const char* source, char dest[], size_t destSize) {
    if (!source || !dest || strlen(source) >= destSize)
        return 1;  // 複製失敗
    strcpy(dest, source);
    return 0;      // 複製成功
}

關鍵點:傳入目標緩衝區大小,檢查源長度嚴格小於目標容量。

題目二:陣列名不可作左值與批量賦值誤區

void test2() {
    char string[10], str1[10];
    for (int i = 0; i < 10; i++)
        str1 = 'a';  // 錯誤:陣列名為常量指標
    strcpy(string, str1);
}

錯誤分析:

  1. 陣列名 str1 是常量指標,不可作左值賦值
  2. 陣列除初始化外不支援批量賦值,需逐元素操作
  3. str1 缺少結束符,strcpy 同樣越界

修正版:

void test2() {
    char string[10], str1[10];
    for (int i = 0; i < 9; i++)  // 預留結束符位置
        str1[i] = 'a';
    str1[9] = '\0';
    strcpy(string, str1);
}

題目三:strlen 未計算結束符導致邊界判斷錯誤

void test3(char* str1) {
    char string[10];
    if (strlen(str1) <= 10)  // 應為 < 10
        strcpy(string, str1);
}

錯誤分析:strlen 不含 \0,當源長度為 10 時實際佔 11 字節,仍會溢出。

修正:if (strlen(str1) < 10 && str1 != NULL)

題目四:指標傳值無法修改呼叫者指向

void GetMemory(char* p) {
    p = (char*)malloc(100);  // 只修改區域副本
}
void Test() {
    char* str = NULL;
    GetMemory(str);
    strcpy(str, "hello world");  // str 仍為 NULL
}

核心問題:C 語言參數傳值,函數內修改 p 不影響外部 str。需傳遞二級指標或返回指標。

修正方案一(二級指標):

void GetMemory(char** p) {
    char* temp = (char*)malloc(100);
    if (temp) *p = temp;
}
void Test() {
    char* str = NULL;
    GetMemory(&str);
    // ...
    free(str);
}

方案二(返回值):

char* GetMemory() {
    return (char*)malloc(100);
}

題目五:返回區域變量地址

char* GetMemory() {
    char p[] = "hello world";  // 區域陣列在堆疊上
    return p;  // 函數返回後記憶體失效
}

原理:區域變量(auto)分配在堆疊,函數結束自動釋放。malloc 分配在堆上,需手動 free。

修正:動態分配並返回堆記憶體指標。

題目六:重複題四邏輯

同樣演示二級指標正確傳遞動態記憶體。

題目七:malloc 返回值未檢查

void Test() {
    char* str = (char*)malloc(100);
    strcpy(str, "hello");  // 若 malloc 失敗返回 NULL,這裡崩潰
    free(str);
}

鐵律:動態分配必檢查返回值。

malloc 內部機制補充

malloc 維護空閒鏈表,尋找合適塊分割分配;free 回收並嘗試合併相鄰塊。長期運行會產生碎片,大塊分配可能觸發整理延遲。若無合適塊返回 NULL,故必須檢查。

總結

這七道題揭示了 C 語言四大核心陷阱:

  1. 緩衝區邊界:永遠預留結束符空間,使用 strncpy/snprintf 或手動檢查長度
  2. 陣列與指標區別:陣列名非左值,不可整體賦值
  3. 參數傳值機制:需修改指標本身時傳二級指標或用返回值
  4. 記憶體生命週期:堆疊自動管理,堆需手動管理,嚴禁返回區域變量地址

掌握這些原理,配合嚴格的防禦性編程習慣,方能寫出健壯的 C 代碼。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved