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

C/C++ 程式設計師面試必考題深度剖析:strcpy、記憶體管理、指標陷阱

     編輯:C++ 入門

前言

C/C++ 面試中,看似簡單的 strcpy、記憶體操作、指標運算題,實則考察候選人對**語言標準、未定義行為、資源管理、邊界條件、防禦性程式設計**的綜合掌握。本文選取經典必考題,從「能跑」到「工業級強健」層層遞進,解析評分細則與核心知識點。

一、strcpy 實作:從 2 分到 10 分的進化

題目:實作 char* strcpy(char* dest, const char* src)

Level 1:最朴素實作 (2 分)

char* strcpy(char* dest, char* src) {
    while ((*dest++ = *src++) != '\0');
}

缺陷: 無 const 正確性、無空指標檢查、無返回值 (無法鏈式呼叫)、dest 修改後無法取得起始位址。

Level 2:加上 const 正確性 (4 分)

char* strcpy(char* dest, const char* src) {
    while ((*dest++ = *src++) != '\0');
}

進步: src 標記 const,表達「唯讀輸入」語意,編譯器可檢測誤寫。

Level 3:防禦性檢查 + 斷言 (7 分)

char* strcpy(char* dest, const char* src) {
    assert(dest != nullptr && src != nullptr); // 僅 Debug 生效
    while ((*dest++ = *src++) != '\0');
}

進步: 明確前置條件,開發期捕獲空指標錯誤。

Level 4:工業級完美實作 (10 分)

char* strcpy(char* dest, const char* src) {
    // 1. 前置條件檢查 (釋出版也可選擇保留或改為錯誤碼)
    if (!dest || !src) return nullptr; // 或 errno = EINVAL; return nullptr;

    // 2. 保存 dest 起始位址以供返回
    char* ret = dest;

    // 3. 複製迴圈 (標準要求包含結束符)
    while ((*dest++ = *src++) != '\0');

    // 4. 返回原始 dest,支援鏈式呼叫:strcat(strcpy(buf, "hello"), " world");
    return ret;
}

核心考點總結

考點標準要求常見遺漏
參數 const 正確性const char* src漏寫 const
空指標處理未定義行為,工業級需檢查無檢查或僅 assert
返回值返回 dest 起始位址無返回或返回錯誤值
重疊記憶體標準未定義 (src/dest 重疊 UB)未說明限制
效能優化字對齊、SIMD、memcpy 內建逐字元複製

二、記憶體操作經典陷阱題

陷阱 1:函式內修改指標參數不影響外部

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

解法: 傳遞指標的指標 char** 或參考 char*&,或返回配置位址。

陷阱 2:返回區域陣列/物件指標

char* GetMemory() {
    char p[] = "hello world"; // 區域陣列,棧上,函式返回即銷毀
    return p; // 返回懸空指標
}

解法: 動態配置 malloc/new、靜態/全域儲存期、呼叫端提供緩衝區、返回 std::string。

陷阱 3:malloc 失敗未檢查

void GetMemory(char** p, int num) {
    *p = (char*)malloc(num); // 可能返回 NULL
    // 缺少 if (*p == NULL) 處理
}

鐵律: **每次動態配置必須檢查失敗**,否則後續解參考必崩潰。

陷阱 4:free 後未置 NULL 產生野指標


free(str);
// str 仍指向已釋放記憶體 → 野指標
// 後續 if (str) 判斷為真,再次使用 → 雙重釋放/寫入已釋放記憶體

規範: free(ptr); ptr = NULL; (或 delete ptr; ptr = nullptr;) 成對出現。

陷阱 5:swap 實作使用未初始化指標


void swap(int* p1, int* p2) {
    int* p;        // 未初始化,野指標
    *p = *p1;      // 寫入隨機位址 → 崩潰
    *p1 = *p2;
    *p2 = *p;
}

正確: 使用區域變數 int tmp = *p1; *p1 = *p2; *p2 = tmp;,完全避免指標。

三、綜合考察點對應知識體系

題目類別核心知識點延伸閱讀
字串操作C 字串慣例、const 正確性、前置/後置條件、重疊 UB、SIMD 優化《C 陷阱與缺陷》、《C++ Primer》字串章
指標/記憶體指標傳值 vs 傳址、儲存期 (自動/靜態/動態/執行緒)、所有權語意、RAII《Effective C++》條款 3, 7, 13, 17、《C++ Core Guidelines》R.1-R.30
錯誤處理斷言 vs 錯誤碼 vs 例外、資源洩漏防護、雙重釋放、Use-after-free《Exceptional C++》、《C++ Core Guidelines》E.1-E.20
未定義行為空指標解參考、緩衝區溢位、有符號溢位、嚴格別名規則、未初始化讀取《C/C++ 未定義行為指南》、UBSan 文件

四、面試加分回答模板

  1. 先說標準語意:「根據 C 標準,strcpy 複製包含結束符的字串,行為未定義若 src/dest 重疊。」
  2. 給出防禦性實作: 展示 Level 4 程式碼,解釋每行用意。
  3. 指出效能優化方向:「實際專案中會使用 __builtin_strcpy 或平台優化 memcpy,針對對齊記憶體用向量化指令。」
  4. 延伸討論安全替代品:「C11 strcpy_s、C++ std::string/string_view、strlcpy (BSD) 避免緩衝區溢位。」
  5. 關聯現代 C++:「新代碼應優先用 std::string、span、format,僅在介接 C API 時手寫 strcpy。」

結語

C/C++ 面試題不考記憶力,考的是**對語言規範的精確理解、對未定義行為的敏感度、對資源管理的嚴謹態度**。一個 10 分的 strcpy,體現的是工程師「將正確性內化為肌肉記憶」的職業素養。建議準備面試時:手寫核心函式 (strcpy, strlen, memcpy, strcmp, strstr, atoi, itoa)、手寫智慧指標/RAII 包裝、手寫執行緒安全單例/鎖自由佇列、熟練解釋每個 UB 的後果與偵測工具。功夫在詩外,基本功扎實,面試自然水到渠成。

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