小端序与内存覆盖:一段UB的C++代码运行原理解析
越界访问C++代码的运行机制解析
首先明确:这段代码属于未定义行为(UB),因为它访问了数组x的越界元素x[3]。我们基于「编译器将全局变量连续排布、无额外优化」的假设场景,拆解其运行逻辑:
#include <stdio.h> int x[] = {1, 2, 3}; char s[] = "hello"; int main() { puts(s); x[3] = ('e' << 16) + ('y' << 8) + 'b'; puts(s); }
1. 假设非UB场景,内存中发生了什么,为何输出bye?
- 全局变量
x和s在程序的全局数据段中连续排布(此处x在前,s在后)。 x是包含3个int元素的数组,在32位系统中每个int占4字节,因此x共占用12字节内存。x[3]属于越界访问,对应的内存地址恰好是s数组的起始位置。- 赋值语句计算后,得到的
int值结构为:高8位是0,次高8位是'e'的ASCII码(101),中间8位是'y'的ASCII码(121),低8位是'b'的ASCII码(98)。这个int值的4个字节会被写入s数组的起始地址,覆盖s的前4个字节。
2. 为何bye的'e'后会自动插入空终止符?
- 原
s数组的内容是'h' 'e' 'l' 'l' 'o' '\0'(共6字节)。 - 写入的
int值的最高8位为0,在小端模式下,这个0字节会被存在s[3]的位置,刚好是字符串的空终止符'\0'。当puts函数输出时,遇到该终止符就会停止输出,因此最终显示bye。
3. 大小端序在此过程中起到了什么作用?
- 大小端直接决定了
int类型数据在内存中的字节存储顺序:- 小端模式(x86架构主流):
int的低字节存储在低地址,高字节存储在高地址。因此赋值的int字节会按'b'、'y'、'e'、0的顺序依次写入s[0]到s[3],形成'b' 'y' 'e' '\0'的有效字符串,最终输出bye。 - 大端模式:
int的高字节存储在低地址,此时s[0]会被写入0,puts会直接输出空字符串,无法得到bye的结果。可见这段代码能输出bye完全依赖系统是小端序。
- 小端模式(x86架构主流):
内容的提问来源于stack exchange,提问作者SomeoneWithPassion
相关产品推荐
相关产品推荐

