技術面試往往聚焦於計算機科學基礎與工程實踐能力的交集。本文精選 10 道高頻面試題,涵蓋算法設計、位運算技巧、C/C++ 指針與內存模型、作業系統原理、網絡協議等核心領域,提供標準答案與深度解析,助你構建完整知識體系。
問題:數組 a[N] 存放 1 至 N-1 的數字,其中一個數字重複一次。要求 O(N) 時間找出該數字。
解法:利用輔助數組標記法(空間換時間),或數學求和法(sum(a) - N*(N-1)/2),或位運算異或法(最優空間 O(1))。
// 標記法 O(N) 時間,O(N) 空間
int find(int a[], int n) {
int *temp = calloc(n, sizeof(int));
for (int i = 0; i < n; i++) {
if (temp[a[i]]) { free(temp); return a[i]; }
temp[a[i]] = 1;
}
free(temp);
return -1;
}
核心結論:(n & (n - 1)) == 0 且 n > 0。
原理:2 的冪次二進制僅有一個 1(如 1000),減 1 後變為全 1(0111),按位與結果為 0。
bool isPowerOfTwo(int n) {
return n > 0 && ((n & (n - 1)) == 0);
}
代碼:
char str1[] = "abc", str2[] = "abc";
const char str3[] = "abc", str4[] = "abc";
const char *str5 = "abc", *str6 = "abc";
char *str7 = "abc", *str8 = "abc"; // C++ 非法,C 警告
結果:0 0 1 1(C++ 編譯器常量合併優化)。
解析:
str1~str4)各自在棧上分配獨立內存,地址不同。str5~str8)指向只讀數據段的同一字面量常量區,地址相同(編譯器優化)。代碼:
int a[5] = {1,2,3,4,5};
int *ptr = (int *)(&a + 1);
printf("%d,%d", *(a+1), *(ptr-1)); // 輸出 2,5
核心區別:
a:數組首元素地址(int*),a+1 偏移 sizeof(int)。&a:整個數組地址(int (*)[5]),&a+1 偏移 5*sizeof(int),指向 a[5](越界一個元素)。ptr 強轉為 int* 後,ptr-1 回退一個 int 大小,指向 a[4](值 5)。破壞任一條件即可預防死鎖。
| 特性 | TCP (傳輸控制協議) | UDP (用戶數據報協議) |
|---|---|---|
| 層級 | 傳輸層 (Layer 4) | |
| 連接性 | 面向連接 (三次握手/四次揮手) | 無連接 |
| 可靠性 | 可靠(序號、ACK、重傳、流控、擁塞控制) | 不可靠,不保證順序、不重傳 |
| 首部開銷 | 最小 20 Bytes,最大 60 Bytes | 固定 8 Bytes |
| 傳輸模式 | 字節流 | 數據報文 |
| 適用場景 | HTTP/HTTPS、FTP、SMTP、郵件、文件傳輸 | DNS、視頻直播、VoIP、即時遊戲、廣播 |
問題:(void *)ptr vs (*(void **))ptr 結果是否相同?
結論:相同(前提 ptr 類型為 void** 或兼容指針類型)。
解析:
(void *)ptr:直接將 ptr 強轉為 void*。(*(void **))ptr:將 ptr 視為 void**(二級指針),解引用獲取其指向的 void* 值。若 ptr 本身指向一個 void* 變量,則結果一致。賦值:*(unsigned int *)0x100000 = 1234;
跳轉執行:
typedef void (*FuncPtr)();
((FuncPtr)0x100000)(); // 或 *((void (*)())0x100000)();
應用場景:嵌入式 Bootloader 跳轉應用程序、記憶體映射 I/O (MMIO) 操作硬體暫存器。
這 10 道題覆蓋了面試高頻考點。建議: