我们在学习C语言的时候经常会碰到指针或者数组下标加1,这也是个令大家非常头疼的问题,那就是它加1以后实际上是加了多少,指针或者数组的下标移动到了哪里。
下面我就通过举几个例子来告诉大家答案。
例1:
#include
int main(int argc, char **argv)
{
int a[3]={
0
};
printf("%0x %0x %0x",a,a+1,&a+1);
return 0;
}
打印结果:bfaf2268 bfaf226c bfaf2274
我们定义了一个整型的一维数组,对于这个数组而言,加1相当于扫过一个int类型,即4个字节,也相当于元素后移一位,所以a与a+1的地址相差4,那么最后一个&a+1呢?
我们知道a本身就是个地址,它是这个数组的首地址,那么我们取a的地址相当于取整个数组的地址,所以加1加的是整个数组,相当于往后移了整个数组,即4*3=12个字节。
例2:
#include
int main(int argc, char **argv)
{
int a[3][3]={1,2,3,4,5,6,7,8,9};
printf("%0x %0x \n",a,a+1);
printf("%0x %0x\n",a[0],a[0]+1);
printf("%d\n",*(*(a+0)+1));
printf("%0x\n",*(a+1));
printf("%0x %0x %0x %0x\n",a+1,*(a+1),*(a+1)+1,&a[1][0]);
int i,j;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
printf("%d ",*(*(a+i)+j));
printf("\n");
return 0;
}
打印结果:
bfcec434 bfcec440
bfcec434 bfcec438
2
bfcec440
bfcec440 bfcec440 bfcec444 bfcec440
1 2 3 4 5 6 7 8 9
我们首先定义了一个二维数组a,它和刚才的一维数组的区别就是a+1指的是数组移动了一行,也就是4*3=12个字节。为什么会这样呢?
在二维数组a中,a和a[0]都是指针,都指向这个数组的第一个元素,但它们却有很大的区别:a是行指针,也就是说它指向的是行,对a加1移动的是一行。而a[0]是列指针,也就是说对a[0]加1只是往后移动了一个元素。
其中a和&a[0]是等价的,当你对a[0]取地址后,它就从指向列指向了行。
a[0]和&a[0][0]还有*(a+0)是等价的,它们都是指向列的。
例3:
#include
int main(int argc, char **argv)
{
int a[3][4]={{1,2,3,4},{3,4,5,6},{5,6,7,8}};
int i;
int (*p)[4]=a,*q=a[0];
printf("%p %p\n",p,p+1);
printf("%p %p\n",q,q+1);
return 0;
}
打印结果:
0xbff30698 0xbff306a8
0xbff30680 0xbff30684
我们定义了一个数组指针p,并且让这个数组指针p指向二维数组a,然后又定义了一个int型指针q指向a[0]。所谓数组指针就是这个指针指向的是一个数组的首地址,而且它不能指向一个一维数组,因为这样会和首元素的首地址相冲突。
所以对于数组加1肯定是行加1,而a[0]是指向列的,所以a[0]+1只是列加1,。
例4:
#include
int main(int argc, char **argv)
{
char *p = "hello";
printf("%p %p\n",p,p+1);
printf("%p %p\n",*p,*p + 1);
printf("%d\n",sizeof(p));
return 0;
}
打印结果:
0x80484e0 0x80484e1
0x68 0x69
4
例5:
#include
int main(int argc, char **argv)
{
int a = 4;
int *p = &a;
printf("%p %p\n",p,p+1);
printf("%p %p\n",*p,*p + 1);
printf("%d\n",sizeof(p));
return 0;
}
打印结果:
0xbfa7b9ec 0xbfa7b9f0
0x4 0x5
4
由例4 例5这两个例子可以看出指针地址加1主要看你定义的指针所指向的类型。
主要是看你定义指针的类型,比如你定义int *p=NULL; 那么int占4个字节。指向int的指针+1,该指针所指的内存地址要+4;如果你是定义 char *p=NULL; 那么char占1个字节。指向char的指针+1,该指针所指的内存地址只要+1。
例6:
#include
int main(int argc, char **argv)
{
int a[2][3]={1,2,3,4,5,6};
int* *p;
p=&a[0];
printf("%p %p\n",*p,*p + 1);
printf("% 0x %0x",p,p+1);
return 0;
}
打印结果:
0x1 0x5
bfa2d998 bfa2d99c
例:7:
#include
int main()
{
char *name[]={"Follow me","BASIC","Great Wall","FORTRAN","Computer desighn"};
char **p;
p=name;
printf("%0x %0x\n",p,p+1);
printf("%0x %0x\n",name,name+1);
printf("%p %p\n",*p,*p + 1);
printf("%p %p\n",*name,*name + 1);
return 0;
}
打印结果:
bf8de058 bf8de05c
bf8de048 bf8de04c
0x8048583 0x8048584
0x8048560 0x8048561
由例6 例7可以看出,如果定义的是二级指针p,那么我们二级指针加1,那么它的地址就是加4,因为它指向的类型是指针类型,所有的指针类型加1都是相当于加了4个字节。而*p就要看它指向的类型了,如果是int就是4个字节,如果是char就是1个字节。
对于指针加1的问题确实比较抽象,难以理解,如果看了以后还有不懂的地方可以查阅相关的资料。