C/C++ 面試中,看似簡單的 strcpy、記憶體操作、指標運算題,實則考察候選人對**語言標準、未定義行為、資源管理、邊界條件、防禦性程式設計**的綜合掌握。本文選取經典必考題,從「能跑」到「工業級強健」層層遞進,解析評分細則與核心知識點。
char* strcpy(char* dest, const char* src)char* strcpy(char* dest, char* src) {
while ((*dest++ = *src++) != '\0');
}
缺陷: 無 const 正確性、無空指標檢查、無返回值 (無法鏈式呼叫)、dest 修改後無法取得起始位址。
char* strcpy(char* dest, const char* src) {
while ((*dest++ = *src++) != '\0');
}
進步: src 標記 const,表達「唯讀輸入」語意,編譯器可檢測誤寫。
char* strcpy(char* dest, const char* src) {
assert(dest != nullptr && src != nullptr); // 僅 Debug 生效
while ((*dest++ = *src++) != '\0');
}
進步: 明確前置條件,開發期捕獲空指標錯誤。
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 內建 | 逐字元複製 |
void GetMemory(char* p) {
p = (char*)malloc(100); // 修改區域副本
}
void Test() {
char* str = NULL;
GetMemory(str); // str 仍為 NULL
strcpy(str, "hello"); // 崩潰
}
解法: 傳遞指標的指標 char** 或參考 char*&,或返回配置位址。
char* GetMemory() {
char p[] = "hello world"; // 區域陣列,棧上,函式返回即銷毀
return p; // 返回懸空指標
}
解法: 動態配置 malloc/new、靜態/全域儲存期、呼叫端提供緩衝區、返回 std::string。
void GetMemory(char** p, int num) {
*p = (char*)malloc(num); // 可能返回 NULL
// 缺少 if (*p == NULL) 處理
}
鐵律: **每次動態配置必須檢查失敗**,否則後續解參考必崩潰。
free(str);
// str 仍指向已釋放記憶體 → 野指標
// 後續 if (str) 判斷為真,再次使用 → 雙重釋放/寫入已釋放記憶體
規範: free(ptr); ptr = NULL; (或 delete ptr; ptr = nullptr;) 成對出現。
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 文件 |
__builtin_strcpy 或平台優化 memcpy,針對對齊記憶體用向量化指令。」strcpy_s、C++ std::string/string_view、strlcpy (BSD) 避免緩衝區溢位。」std::string、span、format,僅在介接 C API 時手寫 strcpy。」C/C++ 面試題不考記憶力,考的是**對語言規範的精確理解、對未定義行為的敏感度、對資源管理的嚴謹態度**。一個 10 分的 strcpy,體現的是工程師「將正確性內化為肌肉記憶」的職業素養。建議準備面試時:手寫核心函式 (strcpy, strlen, memcpy, strcmp, strstr, atoi, itoa)、手寫智慧指標/RAII 包裝、手寫執行緒安全單例/鎖自由佇列、熟練解釋每個 UB 的後果與偵測工具。功夫在詩外,基本功扎實,面試自然水到渠成。