最近在做linux内核中发现,有很多关于指针和数组的应用问题,细细研究,发现受益匪浅,将整个分析和收获分享出来,希望高手指正。
1.指针
指针,顾名思义,就是指向一个内存单元的特殊数据单元,这个很好理解,如:
int a;
int *p;
a = 10;
p = &a;
printf("a=%d,*p=%d\n",a,*p);
上面代码中,p存储的是a变量的地址值,如果直接打印p值,发现p中显示的是一段地址值,即存储a变量的地址值。而*p表示取地址中的变量,即a的值,
上述打印中,a == *p==10 。
而多级指针,也很好理解,即存储的变量是指针变量的地址,如:
int **pp = &p;
其中pp是二级指针,pp中的值存储的是指针变量p的地址在,如果打印pp的值,则存储的是p的地址值,而*pp则存储的是p指向的地址值即a的地址值,因此,
**pp == *p==a;多级指针以此类推,并不难理解。
2.数组
数组,是一段在内存空间连续存储的变量集合,单纯说数组,并不难理解,如
int a[10];
int b[10][10];
其中,a[10]表示一维数组,b[10][10]表示的是二维数组,按照存储方式来说,所有的多维数组其实都是一维数组,是一段连续的存储空间,而数组的访问,是依靠数组名来进行的,而数组名是一种非常特殊的指针,也是本篇文章写作的重点,理解了数组与指针的关系,才敢说,自己刚刚进入了c语言的门。
3.数组与指针
这篇文章,主要是想说数组与指针的问题,前面只是做了简单的介绍,首先,如下代码:
int arryA[10]={0,1,2,3,4,5,6,7,8,9};
printf("arrayA[0]=%d,*arrayA=%d,arrayA[3]=%d,*(arrayA+3)",arrayA[0],*arrayA;arrayA[3],*(arrayA+3));
上述函数的打印结果会发现,arrayA[0]=*arrayA=0;arrayA[3]=*(arrayA+3)=3; 通过上面的程序,可以发现,数组变量名就是一个指针,而后面的[3]等价于指针移动3位。
而对于二位数组,则情况变得复杂起来,如下代码:
int arrayD[3][4]={{0,1,2},{3,4,5},{6,7,8},{9,10,11}};
定义的二位数组,打印会发现 arrayD==*arrayD,这个问题一度令我非常困惑,按照指针的理解,arrayD变量中,存储的地址是arrayD的地址值,而**arrayD == 0,即二位数组的第1个元素arrayD[0][0];按照指针的理解,则会发现逻辑是如下情况arrayD --> arrayD -->arrayD[0][0],非常不好理解,但是确实是这样的,只能理解为数组变量名是一种特殊的指针。而二维数组名究竟是一级指针还是二级指针还真不能靠指针理解,只能作为一种特殊的变量理解,具体分析还在研究中。
而对于数组与指针之间的赋值,则非常有意思,一位数组对应一级指针,二位数组对应二级指针,进行如下操作
int * p = arrayA;
int **pp = arrayD;
发现,p[1]=arrayA[1],p[n]=arrayA[n];可以很好的对应,而pp[0][1]则是错误的访问,pp[0]=0,pp[1]=3;...,这个问题也十分的令人疑惑,这个其实是一个巧合,pp[0]表示的是arrayD[0]+0,而pp[1]表示的是arrayD[0]+sizeof(arrayD[]),即pp的指针向后移动了一个指针单元长度,这样直接将二位数组,赋值给二位指针是一种错误的方式,将一位数组直接赋值给一级指针如果保证指针类型与数组类型相同,也是可以的,如果不同,则也是错误的。
这样,数组是有自己的指针定义方式的,定义如下:
int (*pArry)[];
int(*ppArry)[][Num];
上述分别表示了一维数组指针和二位数组指针,指针赋值可以按照如下方式:
pArray=arrayA;//或者pArray=&arrayA[0]
ppArray=arrayD;//或者ppArray=&arrayD[0][0]
这样就可以直接操作数组指针了,然而,操作数组指针中,发现并不和我们想象的那样,pArray的类型是一位数组类型,则pArray+1表示指针移动了arrayA大小的位置,如果想访问arrayA[0],并不能简单的使用pArray[0]访问,相信很多人都遇到过这种迷惑,那么该如何访问? (*pArray)[n], 这个方式是标准的访问方式,在很长的一段时间里,我完全无法理解这样的访问方式,同样,二位数组的访问也是如此(*ppArray)[0][1],在互联网上还是很少有对这个问题进行说明。
在上面数组和指针分析后,还有一种特别有用的使用方法,如下:
int **p;
如果想反问*p的一位指针,则可以使用p[0],这个使用方式在树形结构中很有用。
4.应用实例