一、指针操作
1.指针的存储结果
#include <stdio.h>
int main()
{
int a = 10;
int* p = &a;
printf("&a= %p\n", &a);
printf("*p= %d\n", *p);
printf("p = %p\n", p);
return 0;
}
由此代码可以清晰看出指针存储结果.
输出结果如下:
&a= 0000009137FEF5F4
*p= 10
p = 0000009137FEF5F4
p储存了变量的地址,*p对其解引用
2.指针运算
了解了指针的工作原理,我们就能对指针进行运算.
代码如下:
#include <stdio.h>
int main()
{
int arr1[5] = { 1,3,5,7,9 };
int* p = arr1;
int* p1 = arr1 + 1;//数组名+1
printf("%d\n", *p + 1);//对p解引用,并+1
printf("%d\n", *(p + 1));//对p+1解引用
printf("%d\n", *p1);
printf("%d\n", p1 - p);//指针相减
return 0;
}
运行结果如下:
*p+1 = 2
*(p+1)= 3
*p1 = 3
p1-p = 1
可知,*p等价于arr1[0]的值,即为1
*(p+1)等价于arr1[1],即为3,也等于数组名+1
两指针相减,表示两个指针指向数组元素之间的差距,并不是指多少字节,而是指多少个类型
二、指针和多维数组
1.指针与多维数组的关系
我们知道在一维数组中,指针表示数组首元素地址
int zippo[4][2];//内含int数组的数组
在二维数组中,首元素是首行数组,即zippo[0],其内含两个整数.
既然zippo[0]是数组,那么其地址应该为其首元素地址,即zippo[0][0]
#include <stdio.h>
int main()
{
int zippo[4][2] = { {1,3} ,{5,7} };//创建二维数组
printf("%p\n", &zippo);//对该数组取址
printf("%p", &zippo[0][0]);
return 0;
}
其结果如下:
000000F691B5F518
000000F691B5F518
地址是相同的.
换言之,zippo是一个占用了两个int对象的地址(相当于zippo+1跨了一行),而zippo[0]是一个占用了一个int对象(zippo[0]+1前进一列)的地址,
但由于首元素开始于同一地址,故值相同.
2.对多维数组指针解引用
解引用一个指针(在指针前使用运算符),或在数组名后使用带下标的 [ ] 运算符,得到对象的值
int main()
{
int zippo[4][2] = { {1,3} ,{5,7} };
int* p1 = &zippo;//此写法是不规范的,下文会详解
printf("**zippo=%d\n", **zippo);
printf("*p1=%d\n", *p1);
int* p2 = &zippo[1];
printf("*p2=%d\n", *p2);
return 0;
}
结果如下:
**zippo=1
* p1 =1
* p2 =5
p本应是首元素zippo[0]地址,但其地址与zippo[0][0]相同,所以&zippo等价于&zippo[0][0],
*p是首元素zippo[0]的值,但zippo[0]本身是一个int类型的地址,地址为
&zippo[0][0],所以 **zippo与 * &zippo[0][0]等价,相当于int类型的值zippo[0][0].
即zippo是地址的地址(指针的指针) 必须解引用两次才能获得原始值.
地址的地址(指针的指针)就是双重间接的例子.
理解思路:
- zippo 二维数组首元素地址(每个元素都是内含两个int类型元素的一维数组) zippo+2
- 二维数组的第三个元素的地址,即zippo[2]
- *(zippo+2) 二维数组的第三个元素的首元素地址
- *(zippo+2)+1 二维数组的第三个元素的第二个元素(int)的地址
-
*(*(zippo+2)+1) 数组第3行第2列的值,zippo[2][1]
3.指向多维数组的指针
如何声明一个指针变量pz指向一个二维数组?
把指针声明指向int的类型还不够,因为指向int只能与zippo[0]的类型相匹配,
说明该指针指向一个int,但二维数组zippo[4][2]的zippo是含有两个int的一维数组,所以p必须指向一个内含两个int的数组,而不是指向一个int值.
我们看以下代码:
int (*pz)[2];//1
int * pax[2];//2
代码 1 表示pz为指向数组的指针,并含有两个int类型值
代码 2 表示pax为内含两个元素的数组,数组内含两个指针,指针指向int类型
产生这样的结果的原因是[ ]的优先级高于 *所以会与pax先结合变为数组, *表示数组内有两个指针(指针数组)
因此我们明白了指针数组与数组指针
- 形如 int* pax[2]; 的指针数组(我把它理解为指针的数组),它首先要是一个数组,然后由 int* 修饰数组的内容,表示其包含 2 个指向 int 的指针
- 而形如int (*pz)[2]; 的数组指针(数组的指针),首先要是一个指针(*与pz结合),而 int 修饰数组 [2] ,使其类型变为整型
int main()
{
int zippo[4][2] = { {1,3} ,{5,7} };
int arr[2] = { 2,4 };
int(*pa)[2] = zippo;\\数组指针,指向int
int* pax[2] = { &zippo,&arr };\\指针数组,指向两个地址
printf("%p\n", &arr);
printf("%p\n", pax[1]);
printf("%d\n", *pa[0]);
printf("%d", *pa[1]);
return 0;
}
&arr=00000002BACFF588
&pax[1]=00000002BACFF588
*pa[0]=1//zippo第一个元素的首元素
*pa[1]=5//zippo第二个元素的首元素
其具体应用来日再谈