首先我们来复习指针的基本知识:
int a=10; //定义一个整型变量a,并将10赋值给a;
int *p=&a; //定义一个整型指针变量p,并将a的地址赋值给p;
p=(int *)1000; //将(int)1000强转为整型指针(int *),并赋值给p;
指针变量的大小(4个字节):
在c语言中,内存可以理解为一个字符数组,基本单位是字节,每个字节包含一个地址,而地址是由CPU的地址总线位数决定的,所有的地址一般称为地址空间,比如32位的CPU,地址总线的位数是32位,它可以描述地址空间为0x0000 0000 0000 0000~(2^32-1),又因为1(字节)=8(位),所以32位的系统(还和编译器有关,编译器是32位),指针变量占4个字节。(64位编译器,指针变量占8个字节)
理解指针“加、减”运算:
int arr[8]={1,2,3,4,5,6,7,8}; //定义一个整型一维数组arr,并赋值;
int *p1=arr; //定义整型指针变量p1,指向arr[0](存储arr[0]的地址)
p1++;
此时p1是加一个字节?一个格子(4个格子)?
假设:p1++是加一个字节;
令:p1=3; //p1++执行后执行
int arr[10] = {1};此时,arr[0]==?
若p1++是一个格子:显然,如果这样移动,指针将变得极其复杂,还会引起数据混乱,所以假设不成立!
令:p1=3; //p1++执行后执行
同理得:此时,arr[1]==3;
结果成立!
int *ip = arr;
ip++;//加一个整型单元格,4字节
short brr[10] = {20,10,30,0x7234};
short *sp = brr;
sp++;//加一个short单元格,2字节
double crr[3] = {12.3};
double *dp = crr;//brr
dp++;//加一个单元格,8字节
指针“加、减”数字(结果还是指针):
int main()
{
int *p = (int *)2000;//(强行转换类型)变量或常量,2000是(int *)类型
printf("%d\n",p+2);//2008,int 4个字节
printf("%d\n",p-2);//1992
printf("%d\n",(short *)p+2);//2004, short 2个字节
printf("%d\n",(short *)p-2);//1996
printf("%d\n",(float *)p+2);//2008, float 4个字节
printf("%d\n",(float *)p-2);//1992
printf("%d\n",(double **)p+2);//2008, double * 4个字节
printf("%d\n",(double **)p-2);//1992
printf("%d\n",(char *)p+2);//2002, char 1个字节
printf("%d\n",(char *)p-2);//1998
printf("%d\n",(unsigned long)p+2);//2002,p已经是usigned long类型,p+2b不是指针加法
printf("%d\n",(unsigned long long)p+2);//1998
return 0;
}
指针“减”指针(指针加指针是非法的)(结果是整型常量):
int main()
{
int arr[10] = {0};
int *p = &arr[1];//a[0]的地址若为x,则&arr[1]==x+4
int *q = &arr[9];//x+36
printf("%d\n",p-q);//-8
printf("%d\n",q-p);//8
printf("%d\n",(short *)q-(short *)p);//16
printf("%d\n",(long *)q-(long *)p);//8
printf("%d\n",(float *)q-(float *)p);//8
printf("%d\n",(long long **)q-(long long **)p);//8
printf("%d\n",(double *)q-(double *)p);//4
printf("%d\n",(char *)q-(char *)p);//32
printf("%d\n",(long )q-(long)p);//32
return 0;
}
int main()
{
int arr[10] = {0};
int *p = &arr[1];//a[0]的地址若为x,则&arr[1]==x+4
int *q = &arr[9];//x+36
printf("%d\n",p-q);//-8
printf("%d\n",q-p);//8
printf("%d\n",(short *)q-(short *)p);//16
printf("%d\n",(long *)q-(long *)p);//8
printf("%d\n",(float *)q-(float *)p);//8
printf("%d\n",(long long **)q-(long long **)p);//8
printf("%d\n",(double *)q-(double *)p);//4
printf("%d\n",(char *)q-(char *)p);//32
printf("%d\n",(long )q-(long)p);//32
return 0;
}
总结:
1、指针+、- 数字:指针需要调整的权重为 sizeof(指针去掉一个*),结果还是指针;
2、指针 + 指针: 非法!
3、指针 - 指针 :合法,结果不是指针!表示间隔的单元个数,需要调整的权重为sizeof(指针去掉一个*)
指针-指针,分两步:(1)算出间隔字节数;(2)除以调整的权重。