为何含指针的C语言代码输出为556而非预期300?求解释
为什么这段C代码输出是556而不是300?
先把咱们要分析的代码贴出来,方便对照:
int main() { int a = 300; char *b = (char *)&a; *++b = 2; printf("%d ",a); return 0; }
核心原因其实是字节序(Endianness) + 你通过char指针直接修改了int变量的单个字节,咱们一步步拆解:
先看
int a = 300;——在绝大多数现代系统里,int是4字节(32位)长度。300转换成十六进制是0x0000012C(也就是1*256 + 44 = 300)。然后
char *b = (char *)&a;——这里你把int变量a的地址强制转换成了char指针。char指针的特点是每次只会访问1个字节的内存,这是整个问题的关键切入点。重点来了:现在主流的CPU(比如x86/x86_64架构)都是用小端序(Little Endian)存储多字节数据。小端序的规则很简单:低字节存在内存的低地址,高字节存在内存的高地址。
所以变量a在内存里的存储状态(按地址从低到高排列)是这样的:
| 相对内存地址 | 存储的字节值 | 对应十六进制 |
|---|---|---|
| &a + 0 | 44 | 0x2C |
| &a + 1 | 1 | 0x01 |
| &a + 2 | 0 | 0x00 |
| &a + 3 | 0 | 0x00 |
- 接下来执行
*++b = 2;——++b会把指针b从初始的&a(低地址)移动到&a + 1的位置,然后给这个地址赋值2。这时候a的内存就变成了:
| 相对内存地址 | 存储的字节值 | 对应十六进制 |
|---|---|---|
| &a + 0 | 44 | 0x2C |
| &a + 1 | 2 | 0x02 |
| &a + 2 | 0 | 0x00 |
| &a + 3 | 0 | 0x00 |
- 最后
printf("%d ",a);读取a的值时,会把这4个字节按小端序重新组合成int类型:也就是0x0000022C,转换成十进制就是2*256 + 44 = 512 + 44 = 556——这就是你实际看到的输出结果。
如果你的系统是大端序(比如某些老款嵌入式设备、PowerPC架构),结果会完全不同,但现在几乎所有PC和服务器都是小端序,所以你得到了556。
总结一下:你通过char指针直接修改了int变量的第二个字节,而小端序的存储方式让这个修改直接改变了int值的“次低位字节”,最终导致结果从300变成了556。
内容的提问来源于stack exchange,提问作者WRICK
相关产品推荐
相关产品推荐

