遇到一道奇怪的关于C指针的练习!
源代码:
#include <stdio.h>
#include <stdlib.h>
void f(void)
{
int a[4];
int *b = malloc(16);
int *c;
int i;
printf("1: a = %p, b = %p, c = %p\n", a, b, c);
c = a;
for (i = 0; i < 4; i++)
a[i] = 100 + i;
c[0] = 200;
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c[1] = 300;
*(c + 2) = 301;
3[c] = 302;
printf("3: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = c + 1;
*c = 400;
printf("4: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
c = (int *) ((char *) c + 1);
*c = 500;
printf("5: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
b = (int *) a + 1;
c = (int *) ((char *) a + 1);
printf("6: a = %p, b = %p, c = %p\n", a, b, c);
}
int main(int ac, char **av)
{
f();
return 0;
}
输出:
1: a = 0xbff3a0a0, b = 0x97f1008, c = 0x8048662
2: a[0] = 200, a[1] = 101, a[2] = 102, a[3] = 103
3: a[0] = 200, a[1] = 300, a[2] = 301, a[3] = 302
4: a[0] = 200, a[1] = 400, a[2] = 301, a[3] = 302
5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
6: a = 0xbff3a0a0, b = 0xbff3a0a4, c = 0xbff3a0a1
其中最奇怪的是第五行的输出:5: a[0] = 200, a[1] = 128144, a[2] = 256, a[3] = 302
涉及到的指令是:
line_n:c = (int *) ((char *) c + 1);
line_m:*c = 500;
在没有执行第line_n行的时候,c的类型是int*,如果此时c+1就相当于在内存中加了4个字节,但是若是先将c强制转换成char*类型,则此时的c+1相当于在内存中加了1个字节!这就是“奇怪”的根本原因,我们看看a[1]=128144,a[2]=256具体是怎么算出来的?
如图所示:
其中注意,Int4字节的是以小端模式存储在内存中的,比如:10进制的400转换成16进制为:0x00000190
高位存储在高字节中,低位存储在低字节中:
所以存储方式是:
0x90
0x01
0x00
0x00
相反,大端模式的存储方式是:
高位存储在低字节中,低位存储在高字节中:
所以对于10进制整形数字400的大端模式的存储方式是:
0x00
0x00
0x01
0x90