也许很多人和我一样,看到这些和指针相关的概念就头疼,但是今天只要耐心看完我接下来的解释与分析就能够做到清楚地判别不同类型的指针和数组。
首先,在接触这些词前,要记住一件事,这些名词都是有规律的,比如:指针数组,这是一个数组,前面的指针是修饰数组的。同理,数组指针就是一个指针,前面的数组是修饰指针的。
目录
指针数组
定义:指针数组就是一个存放指针的数组,即数组中的每个元素的类型都是指针类型。
通常结构:类型* 数组名[数组的长度]
此处的类型是指:数组中的指针是什么类型的指针,这取决于指针所指向的对象
形如:int* arr[10]; //这里是声明了一个 大小为10的整形指针数组
具体使用:
int main()
{
int arr1[3] = { 1,2,3 };
int arr2[3] = { 4,5,6 };
int* parr[2] = { arr1,arr2 };//这里将arr1和arr2的首元素地址存放到指针数组parr中(因为parr中的元素是指针,指针可以存放地址)
int i = 0;
int j = 0;
//通过指针数组去访问指针所指向的数组
for (i = 0;i < 2;i++)
{
for (j = 0;j < 3;j++)
{
printf("%d ", *(parr[i] + j));//parr[i]是确定parr这里的第几个元素的,然后parr[i]+j就是对数组名+某个数j,即可以得到该数组中的下标为j的元素的地址
//然后再对地址进行解引用,就可以打印出来指针数组中的指针所指向的数组了【这里的写法有很多】
}
}
return 0;
}
数组指针
定义:数组指针就是一个指针,该指针指向了一个数组,即该指针中存放的地址为整个数组的地址。
通常结构:数组的类型 (*指针名)[数组的长度]
注意:指针的类型是将指针名去掉后剩下的,即 数组的类型(* )[数组的长度]。
形如:int(*p)[10]; //这里的指针是指向一个大小为10的整形数组,指针的类型就是 int(*)[10]
具体使用:
int main()
{
int arr[5] = { 1,2,3,4,5 };
int(*p)[5] = &arr;//这里的&arr是代表整个数组的地址,而不是首元素的地址
int i = 0;
for (i = 0;i < 5;i++)
{
printf("%d ", *(*p + i));//这里的*p是先对数组的地址进行解引用,解引用后的就是数组首元素的地址了,在首元素的地址上加上i再进行解引用就可以访问第i个元素了
}
}
事实上,我们一般不会使用数组指针在一维数组上,上述代码的目的就是为了打印这个一维数组,我们完全没有必要多此一举弄一个数组指针。而对于二维数组而言,数组指针使用的就比较多了,我们看下面的代码。
int main()
{
int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
int(*p)[3] = arr;//这里的arr是第一行的地址(此时将二维数组想象成一维数组,每一行就是一个元素)
int i = 0;
int j = 0;
for (i = 0;i < 3;i++)
{
for (j = 0;j < 3;j++)
{
printf("%d ", *(*(p+i)+j));//p+i是确定访问第i行的,*(p+i)+j是确定访问第i行的第j个元素的【这里的写法有很多】
}
}
return 0;
}
函数指针
定义:函数指针就是一个指针,该指针指向了一个函数,即该指针中存放的地址为函数的地址(函数名就是函数的地址)。
通常结构:函数的返回类型 (*指针名)(函数参数)
注意:指针的类型是将指针名去掉后剩下的,即 函数的返回类型(* )(函数参数)。
形如:void(*p)(int, int); //这里的指针书指向了一个参数为int和int的,返回类型为void的函数。指针的类型是 void(*)(int, int)
具体使用:
int FindMax(int x, int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 10;
int b = 20;
FindMax(a, b);
int(*pf)(int, int) = FindMax;//定义一个函数指针指向FindMax函数
printf("%d\n", (*pf)(1, 2)); //通过函数指针去调用函数
printf("%d\n", pf(1, 2)); //*其实可以省略(可以直接将pf当做函数名使用)
return 0;
}
函数指针数组
定义:函数指针数组是一个数组,数组中的每个元素是一个函数指针。即该数组为存放函数指针的数组。
通常结构:函数的返回类型 (*数组名[数组的长度])(函数的参数)
形如:void(*arr[10])(int, int)
这里比较绕,可以通过拆解法,去分析这个函数指针数组的结构。
先找到数组名,数组名紧跟着的是数组的长度,对于一个数组而言,将数组名和数组的长度去掉,剩下的就是数组的类型,这里我们去掉arr[10]
剩下的 void(*)(int, int)就是数组的类型,该类型是一个函数指针。
具体使用:
int Add(int x, int y)
{
return x + y;
}
int Sub(int x, int y)
{
return x - y;
}
int Mul(int x, int y)
{
return x * y;
}
int Div(int x, int y)
{
return x / y;
}
int main()
{
int(*pfarr[4])(int, int) = { Add, Sub, Mul, Div };//将每个函数的地址放到函数指针数组中
//计算2x3
printf("%d\n", (*pfarr[2])(2, 3));//pfarr[2]说明他是数组中的第三个元素,然后通过函数指针调用乘法Mul函数
//计算10/5
printf("%d\n", pfarr[3](10, 5)); //作用与(*pfarr[3])(10,5)相同
return 0;
}