示例代码:
#include <stdio.h>
#include <stdlib.h>
void f(void)
{
int a[4];
int *b = (int *)malloc(16); //一个int四个字节,共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; //c指向a
printf("2: a[0] = %d, a[1] = %d, a[2] = %d, a[3] = %d\n",
a[0], a[1], a[2], a[3]);
printf("initial pointer: a = %p, b = %p, c = %p\n", a, b, c);
c[1] = 300;
*(c + 2) = 301;
3[c] = 302; //a[b]=*(a+b),a[5]=*(a+5)=*(5+a)
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指向a[1]。由于a中存int,一个int占四个字节,所以c的地址会+4,而不是+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]);
printf("after c = c + 1: a = %p, b = %p, c = %p\n", a, b, c);
c = (int *) ((char *) c + 1); //但如果先将c转化为字符串,再直接对字符串+1,这样导致c实际地址就是+1
printf("after c = (int *) ((char *) c + 1) : a = %p, b = %p, c = %p\n", a, b, c);
*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;
}
运行结果
- c初始指向a[0]。由于c指向int型,
- 一个int占四个字节,所以当c+1时c的地址会+4,而不是+1,从
0x7fffd33e72c0
到0x7fffd33e72c4
- //但如果先将c转化为字符串,再直接对字符串+1,这样导致c实际地址就是+1,从
0x7fffd33e72c4
到0x7fffd33e72c5
结果详细分析
c = (int *) ((char *) c + 1) 与c=c+1的区别
c = (int *) ((char *) c + 1)
c=c+1
其他
- 如果
int *p=(int*)100
,则(int)p+1和(int)(p+1)
不同,前者是101,但后者是104。当指针加整数时,向第二个例子,整数隐式乘以指针所指向的对象的大小。 p[i]
定义为和*(p+i)
相同,代表p指向的内存的第i个对象,当对象大于1字节时,这条规则起作用&p[i]
和(p+i)
相同,代表p指向的内存的第i个对象的地址
在对内存地址进行加法时,要确定他是·integer addition or pointer addition