在计算机科学中,指针(Pointer)是编程语言中的一个对象,利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元。因此,将地址形象化的称为“指针”。意思是通过它能找到以它为地址的内存单元。
在信息工程中指针是一个用来指示一个内存地址的计算机语言的变量或中央处理器(CPU)中寄存器(Register)【用来指向该内存地址所对应的变量或数组】。指针一般出现在比较接近机器语言的语言,如汇编语言或C语言。面向对象的语言如Java一般避免用指针。指针一般指向一个函数或一个变量。在使用一个指针时,一个程序既可以直接使用这个指针所储存的内存地址,又可以使用这个地址里储存的函数的值
本文侧重于通过几个例子,来解析指针。
数组和指针
1、
1 int a[5]={1,2,3,4,5}; 2 int *p=(int*)(&a+1); 3 printf("%d ",*(p-1));
/* a是一个数组名,也就是数组的首地址。 对a进行取地址运算符,得到的是一个指向数组的指针!!!!这句话尤为重要! 也就相当于 int (*p) [5] = &a; p=&a+1指向的是数组组a[4]的后面一个int单元, p-1指向a[4]=5 p是一个指针,它指向的是一个包含5个int元素的数组!! 那么执行p+1后,p的偏移量相当于 p + sizeof(int) * 5 !! 而程序中强制将指针p转换成一个int* 那么 p -1 其实就是 p - sizeof(int) 所以,p -1 指向了数组中得最后一个元素,也就是 5 */
2、
int a[]={1,2,3,4,5}; int*p[]={a,a+1,a+2,a+3}; int **q=p; printf("%d ",*(p[0]+1)+**(q+2));
/* p[0]+1=a+1; *(p[0]+1)=2; *(q+2)=a+2; *(a+2)=3; 3+2=5; 其中p[0]=a也就是a[0]的地址, p[0]+1=a+1就是a[1]的地址, *(p[0]+1)就是a[1]的值就是2, **q=p --> *q=&p -->表示q保存的是p 的地址,q+2表示p[2]的地址,*(q+2)表示p[2], **(q+2)表示*p[2]表示*(a+2)就是a[2]的值就是3, 所以 *(p[0]+1)+**(q+2)=5 */
3、
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; int (*pt)[4]=a; printf("%d ",(*(pt+2))[2]);
/* 二维数组a[3][4]可以看做是{{1,2,3,4},{5,6,7,8},{9,10,11,12}}; (*(pt+2))[2]的值相当于 *(*(pt+2)+2) p[2]指向a[2]也就是a[2][0]的地址,所以p[2]+2指向a[2][2]的地址,其内容为11。 */
4、
int a[3][2]={1,2,3,4,5}; int *p[3]; p[0]=a[1]; printf("%d ",*(p[0]+1));
// *(p[0]+1)所代表的数组元素是 a[1][1]
5、
static int a[]={5,4,3,2,1}; int *p[]={a+3,a+2,a+1,a}; int **q=p; printf("%d ",*(p[0]+1)+**(q+2));
/* *(p[0] +1 ) = *( *(p+0) + 1) = *(a+3 +1) = a[4] = 1 **(q+2) = *(*(q+2) +0 ) =*( p[2]) = *(a+1) = 4;
*/
6、
int a[10]={1,2,3,4,5,6,7,8,9,10}; int *p=&a[3]; int b=p[5]; printf("%d ",b);
/* a可以理解为这个数组的首地址 a[3]是指向第4个元素 所以p指向第4个元素 p[5]是从p后的5个 也就是第9个元素 所以b=9 */
7、
int a[2][3]={1,2,3,4,5,6}; int *p; p=a[0]; printf("%d ",*(p+3));
// *(p+3)所代表的数组元素是 a[1][0];