🚀个人主页: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 语言联合体和指针的熟练度;
- 写出“最简可运行代码”的能力。