我正在运行这段代码来更好地理解指针.
void foo(void)
{
int a[4] = {0, 1, 2, 3};
printf("a[0]:%d, a[1]:%d, a[2]:%d, a[3]:%d\n", a[0], a[1], a[2], a[3]);
int *c;
c = a + 1;
c = (int *)((char*) c + 1);
*c = 10;
printf("c:%p, c+1:%p\n", c, c+1);
printf("a:%p, a1:%p, a2:%p, a3:%p\n", a, a+1, a+2, a+3);
printf("a[0]:%d, a[1]:%d, a[2]:%d, a[3]:%d\n", a[0], a[1], a[2], a[3]);
printf("c[0]:%d, c[1]:%d\n", *c, *(c+1));
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是:
a[0]:0, a[1]:1, a[2]:2, a[3]:3
c:0xbfca1515, c+1:0xbfca1519
a:0xbfca1510, a1:0xbfca1514, a2:0xbfca1518, a3:0xbfca151c
a[0]:0, a[1]:2561, a[2]:0, a[3]:3
c[0]:10, c[1]:50331648
Run Code Online (Sandbox Code Playgroud)
有人可以解释一下[1]现在是2561吗?
我明白当我们这样做时:
c = (int *) ((char *) c + 1);
Run Code Online (Sandbox Code Playgroud)
c现在指向a [1]的第一个字节后面的4个字节.
但是[1]如何以2561结束呢?
我猜这与字节序有关吗?
c = a + 1;
Run Code Online (Sandbox Code Playgroud)
现在c点1(第二个元素a)
c = (int *)((char*) c + 1);
Run Code Online (Sandbox Code Playgroud)
你用指针算术"欺骗",在地址上加1,无论大小如何int(注意在68000这样的旧机器上它是不合法的,它不能容忍多字节访问奇数地址,或者能完成这项工作,虽然速度慢了很多,但是因为你没有注意到它,例如它在68020上工作但速度较慢).
现在c指向最后3个字节a[1]并在第一个字节溢出a[2],所以当你这样做时:
*c = 10;
Run Code Online (Sandbox Code Playgroud)
因为你的机器是小端,你将离开前导1值,10在下一个位置写入,然后在后面输入零,从而破坏前导2字节a[2]
所以现在:
a[1] = 1 + (10<<8) = 2561
a[2] = 0
Run Code Online (Sandbox Code Playgroud)
结果在大端机器上有所不同:
PowerPC大端(如果int是32位,否则它是一个不同的结果):
a[1] = 10485760
a[2] = 2 // first byte is overwritten, but with zero
Run Code Online (Sandbox Code Playgroud)
六万八千零一十分之六万八千:
bus error (coredump) / guru meditation
Run Code Online (Sandbox Code Playgroud)
总结一下:不要违反严格的别名规则
| 归档时间: |
|
| 查看次数: |
99 次 |
| 最近记录: |