解析C语句`c = (int *) ((char *) c + 1)`的作用及输出异常
MIT 6.828指针练习:偏移指针导致的内存覆盖问题解析
你对第5段输出中a[1]=128144、a[2]=256的结果困惑,根源是c = (int *) ((char *) c + 1); *c = 500;这句的指针操作,下面一步步拆解:
先回顾第4步结束后的状态
第4步执行了:
c = c + 1; *c = 400;
此时:
c原本指向数组a的起始地址(a[0]),int*类型指针+1会偏移4字节(对应int的大小),所以c+1后指向a[1]的起始地址。- 赋值
*c=400后,a[1]的值被设为400,数组状态为:a[0]=200, a[1]=400, a[2]=301, a[3]=302。
解析关键语句c = (int *) ((char *) c + 1);
这行是字节级别的指针偏移,拆解每一部分:
(char *) c:把int*类型的c强制转为char*类型。- 指针类型决定运算步长:
int*每次±1偏移4字节,char*每次±1仅偏移1字节(对应char的大小)。
- 指针类型决定运算步长:
((char *) c + 1):对char*类型指针做+1操作,让指针地址向前移动1字节。- 此时
c原本指向a[1]的起始地址,移动后指向a[1]的第2个字节位置(而非下一个int的起始位置)。
- 此时
(int *) (...):把偏移后的char*指针强制转回int*类型。- 此时
int*类型的c指向a[1]第2字节的位置,后续对*c赋值会覆盖从这个位置开始的4个连续字节。
- 此时
分析*c = 500带来的内存变化
结合小端字节序(现代x86/x86_64系统默认采用,低字节存在内存低地址)分析:
- 先把数值转成十六进制:
- 400 =
0x190,小端存储时,a[1]的4字节内存为:0x90 0x01 0x00 0x00(低字节0x90在最前面)。 - 500 =
0x1F4,小端存储时,4字节为:0xF4 0x01 0x00 0x00。
- 400 =
当c指向a[1]的第2字节时,赋值*c=500会覆盖以下4个字节:
| 内存位置 | 原字节值 | 覆盖后字节值 |
|---|---|---|
| a[1]的第2字节 | 0x01 | 0xF4 |
| a[1]的第3字节 | 0x00 | 0x01 |
| a[1]的第4字节 | 0x00 | 0x00 |
| a[2]的第1字节(原301的低字节0x13) | 0x13 | 0x00 |
将覆盖后的字节重新组合成int:
a[1]的4字节变为0x90 0xF4 0x01 0x00,按小端转十进制为0x0001F490 = 128144,对应输出的a[1]=128144。a[2]的4字节变为0x00 0x01 0x00 0x00,转十进制是256,对应输出的a[2]=256。
内容的提问来源于stack exchange,提问作者zbo
相关产品推荐
相关产品推荐

