指针、数组、函数的“复杂关系”
程序员文章站
2022-06-09 13:30:05
...
一、指针数组
①定义
- 指针数组
- 首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身决定。它是“储存指针的数组”的简称。
例如:int * p1[10]; 这是一个数组,其包含10 个指向int 类型数据的指针,即指针数组。int *修饰数组的元素。
②图示
int * p1[10]
int * | int * | int * | int * | int * | int * | int * | int * | int * | int * | int * | int * | int * | int * | int * | int * |
---|
③总结
- 应用
- 1.指针数组常用在主函数传参,在写主函数时,参数有两个,一个确定参数个数,一个这是指针数组用来接收每个参数(字符串)的地址。
int main(int argc, char *argv[])
- 2.子函数传参的时候,传递数组的首地址,应该用二级指针接收。
void fun(char **pp);//子函数中的形参
fun(char *p[]);//主函数中的实参
二、数组指针
①定义
- 数组指针
- 首先它是一个指针,它指向一个数组。在32 位系统下永远是占4 个字节,
不能直接得出它指向的数组占多少字节。它是“指向数组的指针”的简称。例如:int (*p2)[10]; p2 是一个指针,它指向一个包含10 个int 类型数据的数组,即数组指针。int 修饰数组的内容。
②图示
int (*p2)[10] ( p2即数组的首地址)
int | int | int | int | int | int | int | int | int | int |
---|
③应用 ##
-
1.
int main()
{
char a[5] = {'A', 'B', 'C', 'D'};
char (*p3)[5] = &a;
char (*p4)[5] = a;//左边的类型是指向整个数组的指针,右边的数据类型是指向单个字符的指针,会进行隐式的类型转换,将a 指针转换为指向整个数组的指针
printf("%p \n",a);//数组首元素的地址
printf("%p \n", p3);//&a 是整个数组的首地址
printf("%p \n", p4);//a是数组首元素的首地址
printf("%p \n", a + 1);//跳过一个char 类型的字节
printf("%p \n", p3 + 1);//跳过一个指针数组的字节
printf("%p \n", p4 + 1);//转换后 + 1 会跳过一个指针数组的字节
system("pause");
return 0;
}
-
2.
int main()
{
char a[5]={'A','B','C','D'};
char (*p3)[10] = &a;
char (*p4)[10] = a;
printf("%p \n",a);//数组首元素的地址
printf("%p \n", p3);//&a 是整个数组的首地址
printf("%p \n", p4);//a是数组首元素的首地址
printf("%p \n", a + 1);//跳过一个char 类型的字节
printf("%p \n", p3 + 1);//跳过一个指针数组的字节
printf("%p \n", p4 + 1);//转换后 + 1 会跳过一个指针数组的字节
system("pause");
return 0;
}
④总结
- 应用
- 数组指针是一个指针,可以用来接收一个二维数组的地址。
void fun(int (*P)[4]);//子函数中的形参,数组指针
a[3][4] = {0};//主函数中定义的二维数组
fun(a);//主函数调用子函数的实参,是二维数组的首元素首地址
三、函数指针
①定义
- 函数指针
- 函数指针就是函数的指针。它是一个指针,指向一个函数。
例如:void (*pfun1)(); pfun是一个指针变量,它指向一个函数,这个函数没有参数,函数的返回值为一个空类型。
②应用
1.
#include <stdio.h>
#include <string.h>
include <asssert.h>
char * fun(char * p1,char * p2)
{
assert(p1 != NULL);
assert(p2 != NULL);
int i = 0;
i = strcmp(p1, p2);//字符串比较,若两者相等返回p1;否则返回 p2
if (0 == i)
{
return p1;
}
else
{
return p2;
}
}
int main()
{
char * (*pf)(char * p1, char * p2);//pf是一个指针,指向一个参数为两个 char *,返回类型为 char *的函数
pf = &fun;//将函数fun的地址赋给pf
printf("%s \n", (*pf) ("aa", "bb"));
return 0;
}
四、函数指针数组
①定义
- 函数指针数组
- 把函数的地址存到一个数组中,那这个数组就叫函数指针数组。
例如:char * (*pf[3])(char *p); 它是一个数组,数组名为pf,数组内存储了3 个指向函数的指针。这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。
②应用
1.转移表实现计算器
#include <stdio.h>
int Add(int a, int b)
{
return a + b;
}
int Sub(int a, int b)
{
return a - b;
}
int Mul(int a, int b)
{
return a*b;
}
int Div(int a, int b)
{
return a / b;
}
int div(int a, int b)
{
return a / b;
}
int main()
{
int x = 0;
int y = 0;
int input = 1;
int ret = 0;
int(*p[5])(int x, int y) = { 0, Add, Sub, Mul, Div }; //转移表数组存放了不同子函数的地址
while (input)
{
printf("*************************\n");
printf(" 1:Add 2:Sub \n");
printf(" 3:Mul 4:Div \n");
printf("*************************\n");
printf("请选择:");
scanf("%d", &input);
if ((input <= 4 && input >= 1))
{
printf("输入操作数:");
scanf("%d%d", &x, &y);
ret = (*p[input])(x, y);
printf("ret = %d\n", ret);
}
else
printf("输入有误\n");
}
system("pause");
return 0;
}
③总结
- 作用
- 函数指针数组在子函数较多时可以通过不同的调用方法调用函数就来减少代码,使其更加简便。
五、指向函数指针数组的指针
①定义
- 指向函数指针数组的指针
- 指向函数指针数组的指针是.一个指针,指针指向.一个 数组 ,数组的元素都是函数指针 。
例如:char * ((*pf)[3])(char p); pf 是指针。这个指针指向一个包含了3 个元素的数组;这个数组里面存的是指向函数的指针;这些指针指向一些返回值类型为指向字符的指针、参数为一个指向字符的指针的函数。
②应用
#include <stdio.h>
#include <string.h>
char * fun1(char * p)
{
printf("%s\n", p);
return p;
}
char * fun2(char * p)
{
printf("%s\n", p);
return p;
}
char * fun3(char * p)
{
printf("%s\n", p);
return p;
}
}
intmain()
{
char * (*a[3])(char * p);//函数指针数组a
char * (*(*pf)[3])(char * p);//指向函数指针数组的指针pf
pf = &a;
a[0] = fun1;//函数名即函数地址
a[1] = &fun2;
a[2] = &fun3;
pf[0][0]("fun1");
pf[0][1]("fun2");
pf[0][2]("fun3");
system("pause");
return 0;
}
③总结
- 无论是指向函数指针数组的指针,还是其它的内容,都应该注意 * 和 [ ] 的结合,从而来辨清其概念。
推荐阅读