🚀個人主頁:BabyZZの秘密日記
📖收入專欄:C語言
🌍文章目入
- 1. 題目重現
- 2. 大小端到底在比什么?
- 3. 解法一:聯合體(union)
- 為什么一行就夠?
- 使用示例
- 4. 解法二:強制類型轉換 + 指針
- 5. 兩種寫法的對比
- 6. 常見追問 & 回答技巧
- 7. 小結
1. 題目重現
在百度早期的校招面試里,曾經出現過這樣一道 C 語言題:
“給你 3 行代碼,如何判斷當前機器是大端(Big-endian)還是小端(Little-endian)?”
乍一看,這似乎只需要把 1 寫進一個整型變量,再逐字節讀出來即可。但如何用“最簡潔、最優雅”的方式實現,就體現功底了。今天把當年在面試官電腦上敲出的兩種經典寫法整理出來,順便聊聊背后的原理與可移植性。
2. 大小端到底在比什么?
- 小端(Little-endian):低地址放“低字節”。
例如0x12345678
在內存里依次是78 56 34 12
。 - 大端(Big-endian):低地址放“高字節”。
同樣0x12345678
在內存里依次是12 34 56 78
。
只要把一個 int
類型的 1
寫到內存里,再去讀它的首字節,就能知道結果:
- 讀出來是
0x01
→ 小端 - 讀出來是
0x00
→ 大端
3. 解法一:聯合體(union)
int check_sys(void)
{union {char c;int i;} u;u.i = 1;return u.c; /* 1 表示小端,0 表示大端 */
}
為什么一行就夠?
union
的所有成員共享同一塊內存。u.i = 1;
后,低地址那 1 byte 就是u.c
。- 直接返回
u.c
,天然地把大小端信息映射成 0/1。
使用示例
int main(void)
{printf("%s\n", check_sys() ? "小端" : "大端");return 0;
}
4. 解法二:強制類型轉換 + 指針
int main(void)
{int a = 1;char *p = (char *)&a;puts(*p ? "小端" : "大端");return 0;
}
- 把
int*
強轉成char*
,直接解引用首字節。 - 思路與聯合體完全一致,只是寫法更“指針”。
5. 兩種寫法的對比
維度 | union 版 | 指針版 |
---|---|---|
可讀性 | 直觀,一眼看懂共享內存 | 需要理解強制轉換 |
代碼行數 | 3 行(含聲明) | 3 行 |
可移植性 | 100% C 標準 | 100% C 標準 |
面試官喜好 | 更“炫技” | 更“基礎” |
6. 常見追問 & 回答技巧
Q1:為什么不用位運算?
位運算只能拿到數值高低位,無法感知內存地址順序。
Q2:能否寫成宏?
可以,但注意副作用:
#define IS_LITTLE_ENDIAN() (*(char *)&(uint16_t){1})
Q3:網絡字節序是什么?
網絡協議統一采用大端,因此 htons/ntohl
系列函數會在小端機器上做交換。
7. 小結
一道看似簡單的大小端問題,其實考察了:
- 對內存布局的理解;
- 對 C 語言聯合體和指針的熟練度;
- 寫出“最簡可運行代碼”的能力。