一,指针数组和数组指针(伟大的华清牟老师上课笔记)
什么是指针?
存放地址的变量。
指针变量只能存放地址,地址也只能存在指针变量中。
地址有两种运算:
偏移:+ -
```
int a;
printf("%p %p\n", &a, &a+1);//差4个字节,因为是整型的地址。
```
间接:* 单目运算 ,间接运算的运算的对象只能是地址。间接运算得到的结果是地址对应的对象本身,不是数值。绝大部分情况下运算得到的都是变量。我们能得到的常量的地址只有字符串常量。
```
int a;
*&a;//&a运算得到a的地址,*&a对a的地址进行间接运算,得到变量a本身。
*&a = 10;//*&a对a的地址进行间接运算,得到变量a本身,再进行=运算,将右值赋给左值。
```
定义指针
*
在C/C++中出现在声明和定义语句中的符号都不是运算符,都是用来表示标识符身份的符号。
```
* 指针变量
[] 数组
() 函数
int* p;//*说明p是指针变量,int说明p中存放int类型的地址。地址是有类型。
int a;
int* p = &a;//给指针变量p初始化,p指向a
int b;
p = &b;//把b的地址赋值给p,p指向b
*p = &a;//错误*p得到int类型变量,int类型变量不能存放地址。
```
指针和数组的关系
数组名是数组的首地址,而且是常量,地址是数组元素类型。
## 1. 指针数组
在分析一个标识符的含义时,如果标识符被很多符号修饰,由近及远先右后左。
本质:是数组。 每个元素都是一个指针。
先看a右边的[]确定a是数组,5个元素,*说明数组的元素是指针,int说明元素是存放int类型地址的指针。
int *a[5]; |int *|int *|int *|int *|int *|
每个元素都是指针。指针名称:
a[0] int*
a[1] int*
a[2] int*
a[3] int*
a[4] int*
### 示例1:
![image-20220718092433280](day5/image-20220718092433280.png)
```C
#include <stdio.h>
int main()
{
int a = 90,b = 55,x = 10;
int *p[3] = {&a,&b,&x};//使用abx三个变量的地址初始化指针数组中的三个元素。
int i;
for(i=0; i<3; i++)
{
printf("%p\n", p[i]);//p[i]是数组i元素 等价于*(p+i)
printf("%d\n ",*p[i]);//对p[i]进行间接运算,得到p[i]指向的变量本身,等价于**(p+i)
/*
p+i得到i元素的地址,地址偏移运算
*(p+i) 得到i元素本身
**(p+i)对i元素进行间接运算,因为i元素是指针变量,最后得到i元素指向的变量本身
i=0得到a本身 i=1得到b本身 i=2得到x本身
*/
printf("%d\n", **(p+i));
}
return 0;
}
```
### 示例2:
![image-20220718093404213](day5/image-20220718093404213.png)
```C
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,90};
int b[5] = {55,6,7,8,9};
int c[5] = {7,8,7,8,6};
int *p[3] = {a,b,c};//指针数组的三个元素分别指向3个int类型的数组
int i,x;
for(x=0; x<3; x++)//遍历数组p
{
for(i=0; i<5; i++)
{
/*
p[x]等价*(p+x)
p[x][i]等价于*(p[x]+i)
*/
printf("%d ", p[x][i]);
/*
p+x 得到x元素的地址
*(p+x) 得到x元素本身,x元素是指针变量,指向一个数组
*(p+x)+i 得到x元素指向的数组的i元素的地址
*(*(p+x)+i) 得到x元素指向的数组的i元素本身
*/
printf("%d ", *(*(p+x)+i));
}
printf("\n");
}
}
```