先定义几个指针变量:
int *pt;
int arr[10];
int *parr[10];
int (*arrp)[10];
int ar[5][10];
int **ptr;
(1)pt是指向整型变量的指针变量
int a;
pt = &a;这是对pt进行初始化,没有初始化的pt不能使用,否则是不合法的;
pt就是存放a的地址,pt指向的类型是int型,pt本身的类型是int*型,&pt是指针变量pt的存放地址,&pt的类型是int**型
注:无论pt有没有进行初始化,&pt是可用的,因为编译器在编译时,符号表中会为pt分配地址&pt,但是如果pt没有初始化,则pt的值是任意的,因此未初始化的pt是不能调用的,因为pt可能指向任何地方;
(2)arr[10]是整型数组
arr是数组名,在表达式中,arr代表数组首元素的首地址,因为 arr = &(*arr) = &(*(arr+0)) = &(arr[0])= &arr[0],数据类型是int*,这里要区分两个概念,数组首元素的首地址和数组的首地址,在数值上这个值是相同的,但是数据类型不同
数组的首地址的是什么呢,&arr才是数组的首地址,数据类型是int (*) [10] 或者写成(int[10])*,后者比较好理解。
arr和&arr在数值上是相等的,因为无论是整个数组的首地址还是数组第一个元素的首地址,都是相等的。
不同的是数据类型不同,在什么时候体现呢:
就在对指针进行加减运算的时候:
arr+1:就是对arr表示的地址+4,此时指向arr[1]因为是整型数组,每个元素占4个字节,因为当arr移动一个位置,地址+4
&arr+1,:就是对&arr表示的地址+10,此时指向arr[10],当然,arr[10]是不存在的。
(3)parr是指针数组,即数组parr中的每个变量都是int*型
这是因为下标引用符[]优先级要比*高,因此变量名parr先和[]结合构成数组parr[10],然后再与int*结合,构成整型指针数组。
parr的数据类型是int**;
parr[0]的数据类型是int*
&parr的数据类型是int(**)[10]或者说是(int[10])**
(4)app是数组指针,或者说是行指针,因为指针指向的是一行元素而非单个元素,数据类型是int(*)[10],或者说是int
app++;就是对app表示的地址+40,因为app自增就是移动一行,因此才能被行指针,所以可以将app = &arr;
(5)int ar[5][10]:二维数组
ar是二维数组名,ar = &(*(ar+0))=&ar[0],很明显,ar是指向第一行的指针变量,数据类型是int(*)[10]或者是(int[10])*,ar+1 = &ar[1]表示指向第二行的指针变量
所以ar+i是行指针,指向每一行
所以能够:app = ar;
(6)int **ptr是二级指针
可以进行ptr = &pt