数组名与指针1

数组名和指针非常相似,能用&和*运算,但也有很大的不同,两者不能混为一谈。    数组名是地址常量,不用存到储存空间里,所以对数组名取地址不能用取一个储存空间的地址来理解(数组名根本不在什么储存空间里存着)。 指针是地址变量,与其他的变量一样,定义的时候就会为它分配一个储存空间(4字节),不同的指针类型在指针自加时就会让指针往后移不同的位数。比如int a[5],*p1=&a[0];char *p2=&a[0];因为p1是int *型指针,自增会移sizeof(int)位,p1++;后p1的值就是&a[1]。而p2++;p2并不会指向a[1],因为p2只移sizeof(char)=1位。不只是自增,指针的加减都是这个规律。        回到主题,以例子来讲解:    int a[2][3]={1,2,3,4,5,6};    int *p1=a[0];    int *p2=a;    int (*p3)[3]=a;    假设a[0][0]的地址是2000,int 占4字节。(声明:下面的等于只说明它们的数值相等,并不代表它们的意义相同)    &a=a=*a=&a[0]=a[0]=&a[0][0]=2000;    &(a+1)=a+1=*(a+1)=&a[1]=a[1]=&a[1][0]=2012;    *a+1=&(*a+1)=a[0]+1=&(a[0]+1)=&a[0][1]=2004;     **a=a[0][0]=1;     *(*(a+i)+j)=a[i][j];     从中可以看出a可以看做一维数组a[2]的数组名,a[i]可以看做a[i][3]的数组名,因为数组名是地址常量,对数组名取地址得到的数值是它本身的值,由于对普通常量取地址(比如&2)是错误的,所以把对数组名取地址看做特殊处理。     接下来对指针p1 p2 p3进行研究     经过测试得出结论:p1和p2没有什么区别,它们都是int *型指针,p1存的地址是2000,p2也是,*p1等于1,p2也是,*(p1+1)=a[0][1]=2,p2也是,同时测试出指针与数组名的不同:p1=a[0],&a[0]等于2000,但是&p1的值是分配给指针变量p1的储存空间的地址,并不是2000,p2=a,*a=a[0]=2000,**a=a[0][0]=1,但是*p2=1,**p2是非法操作,因为p2只是一个普通的一维指针,它指向的就是地址为2000的变量a[0][0]。     p3就不同了,,p3是(int *)[3]型指针,具有数组名的某些特点,也具有二级指针的一些特点,p3自增时会移动4*3=12位,p3的值是a就是2000,&p3没问题,是储存p3空间的地址,p3+1=&a[1]=2012,而*p3=a[0]=2000,p3储存的地址是2000,它做连接访问运算*时的值并不是储存在地址为2000的值1,而是2000!同样,*(p3+1)=2012,也不是4!只有做两次间访运算才表示存在数组中的值,这与二级指针类似,但又不一样,因为它指向的不是指针变量。     再做测试:     *(p3+i)=a[i]=*(a+i),     *(p3+i)+j=&a[i][j]=*(a+i)+j),     *(*(p3+i)+j)=a[i][j]=*(*(a+i)+j),     从中可以看出p3和a很相似。     我将p3的这两个特殊性质归于(int *)[N]型行指针变量的性质。     (第一次写博客→→)

猜你喜欢

转载自blog.csdn.net/qq_41260042/article/details/78976965