指针有以下两种算术运算:
(1) 指针+/-数字
(2)指针-指针
1> 加一个字节
2> 加一个单元格
3> 加整个数组
1> 若加的是整个数组的话,直接从数组的首部跑到尾部了,起不到遍历数组中每个元素的作用,所以这种想法是错误的;2> 若加的是一个单元格,如下所示
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p=a;
假设数组a的首地址为100,这时数组a中的元素存放位置如下所示:
100 104 108 112 116 120 124 128 132 136
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
现在我们只看上表的前两个单元格,一个字节8位,int型为4个字节,每个单元格32位,我们将其扩大4倍,得到的每个新单元格存放8位,8位太长,所以我们用16进制表示,a[0]=10,a[1]=2,其对应的16进制分别为0000000a,00000002,按小端存放,地地址放小数据,如下所示:
100 101 102 103 104 105 106 107
0a | 00 | 00 | 00 | 02 | 00 | 00 | 00 |
*p=20;
20对应的十六进制为00000014,如果p++加的是一个单元格,如下所示:
100 101 102 103 104 105 106 107
0a | 14 | 00 | 00 | 00 | 00 | 00 | 00 |
a[0]=0x0000140a,a[1]=00000000,对应的十进制分别为a[0]=5130,a[1]=0,这种方法很麻烦,得到的结果也不是我们想要的,所以不采用这种想法;当然这种方法可用如下程序实现:
#include <stdio.h>
int main()
{
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p=a;
*p=10;
p=(int *)((int)p+1);
*p=20;
printf("%08x %08x\n",a[0],a[1]);
printf("%d %d\n",a[0],a[1]);
return 0;
}
结果如下:
综上所述:指针+1:加一个单元格
指针-1:减一个单元格
(1)指针+/-数字:需要调整,调整的权重为sizeof(指针去掉一个*)
int main()
{
int *p=(int *)2000;
printf("%d\n",p+4);//2016
//指针p加4个单元格,每个单元格4个字节,2000+4*4=2016
printf("%d\n",(short *)p+4);//2008
//short *去掉一个*为short,short 2个字节,指针p加4个单元格,每个单元格2个字节,2000+4*2=2008
printf("%d\n",(double *)p+4);// 2000+4*8=2032
printf("%d\n",(double **)p+4);// 去掉一个*为(double *),指针4个字节,2000+4*4=2016
printf("%d\n",(float *)p+4);//2000+4*4=2016
printf("%d\n",(unsigned short *)p+4);// 2000+4*2=2008
printf("%d\n",(long *)p+4);// 2000+4*4=2016
printf("%d\n",(char *)p+4);// 2000+4*1=2004
printf("%d\n",(unsigned long long)p+4);//括号内没有* ,p为普通变量,2000+4=2004
return 0;
}
int main()
{
int *p=(int *)0x2010;
printf("%x\n",p-2);//2008
//指针p减2个单元格,每个单元格4个字节,0x2010-2*4=2008
printf("%x\n",(short *)p-2);//200c
//short *去掉一个*为short,short 2个字节,指针p减2个单元格,每个单元格2个字节,0x2010-2*2=200c
printf("%x\n",(unsigned long *)p-2);//0x2010-2*4=2008
printf("%x\n",(long long *)p-2);//0x2010-2*8=2000
printf("%x\n",(float *)p-2);//0x2010-2*4=2008
printf("%x\n",(double *)p-2);//0x2010-2*8=2000
printf("%x\n",(char *)p-2);//0x2010-2*1=200e
printf("%x\n",(unsigned long)p-2);//括号内没有* ,p为普通变量,0x2010-4=200e
return 0;
}
(2)指针-指针:间隔的单元个数,不是字节数,有正负
1> 算出字节数 2> 除以调整的权重
int main()
{
int arr[10]={1};
int *p=&arr[1];
int *q=&arr[9];
printf("%d\n",p-q);//-8
printf("%d\n",q-p);//8
printf("%d\n",(short *)q-(short *)p);//16
//q-p间隔8个单元格,每个单元格4个字节,共32个字节,short *去掉一个*为short,short 2个字节,32/2=16
printf("%d\n",(double *)q-(double *)p);// 32/8=4
printf("%d\n",(int ***)q-(int ***)p);// int ***去掉一个*为int **,int ** 4个字节,32/4=8
printf("%d\n",(char **)q-(char **)p);// char **去掉一个*为char *,char * 4个字节,32/4=8
printf("%d\n",(long)q-(long)p);//32
}
总结:指针的所有算术运算都需要调整,调整的权重为sizeof(指针去掉一个*)