6. 函数指针数组
7. 指向函数指针数组的指针
8. 回调函数
9. 指针和数组面试题的解析
函数指针数组
指针数组,本质上是一个数组,数组里存放的内容是指针变量
int* p[5]={&a,&b,&c};
函数指针,是一个指针,指针指向了函数名称(函数地址)
int Add( int x, int y )
{
int z=x+y;
return z;
}
int main()
{
int (*p)( int , int )=Add
}
当有多个函数需要存放其地址时,就需要函数指针数组
int Add( int x, int y )
{
int z=x+y;
return z;
}
int Sub( int x, int y )
{
int z=x-y;
return z;
}
int Mul( int x, int y )
{
int z=x*y;
return z;
}
int Div( int x, int y )
{
int z=x/y;
return z;
}
switch实现
int main()
{
int x, y, input;
do
{
memu();
printf("请输入您的选择->\n");
scanf("%d", &input);
switch(input)
{
case 1:
printf("请输入您的操作数\n");
scanf("%d%d", &x, &y);
printf("%d",Add(x,y));
break;
case 2:
printf("请输入您的操作数\n");
scanf("%d%d", &x, &y);
printf("%d",Sub(x,y));
break;
case 3:
printf("请输入您的操作数\n");
scanf("%d%d", &x, &y);
printf("%d",Mul(x,y));
break;
case 4:
printf("请输入您的操作数\n");
scanf("%d%d", &x, &y);
printf("%d",Div(x,y));
break;
case 0:
printf("退出成功\n");
break;
default:
printf("请重新选择\n");
}
}while(input)
return 0;
}
函数指针用途:转移表
通过函数指针数组实现,减少了代码的冗余情况,而且后期更加便于维护
int main()//转移表实现
{
int x, y, input;
int(*pfun[5])(int,int) = {0,Add,Sub,Mul,Div};
do
{
memu();
printf("请输入您的选择->\n");
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("请输入您的操作数\n");
scanf("%d%d", &x, &y);
int ret = pfun[input](x, y);
printf("%d\n", ret);
}
else if (input == 0)
{
printf("退出成功\n");
}
else
{
printf("请重新选择\n");
}
} while (input);
return 0;
}
回调函数
回调函数就是通过函数指针调用的函数。如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的方式直接调用,而是由另一方调用的。
利用回调函数也可以解决上述代码冗余的问题
void Calculator(int (*pfun)(int,int))
{
printf("请输入您的操作数\n");
scanf("%d%d", &x, &y);
printf("%d",pfun(x,y));
}
int main()
{
int x, y, input;
do
{
memu();
printf("请输入您的选择->\n");
scanf("%d", &input);
switch(input)
{
case 1:
Calculator(Add);
break;
case 2:
Calculator(Sub);
break;
case 3:
Calculator(Mul);
break;
case 4:
Calculator(Div);
break;
case 0:
printf("退出成功\n");
break;
default:
printf("请重新选择\n");
}
}while(input)
return 0;
}
回调函数的补充使用实例
void print(char* str)
{
printf("&s",str);
}
void test(void (*p)(char*))
{
printf("test\n");
p("abc");
}
int main()
{
test(print);
return 0;
}
指向函数指针数组的指针
创建一个指针,它指向数组,数组是函数指针数组,所以指针是数组指针
int main()
{
int arr[4]={0};
int* parr[4]=&arr;//对于数组来说,创建一个数组指针
int (*pFun)(int,int)=Add;
int (*pFun[4])(int ,int)={Add,Sub,Mul,Div};//创建一个函数指针数组来存放函数地址,其本质还是一个数组,因此也可以再创建一个数组指针,来存放这个(函数指针)数组
int(* (*ppFun)[4])(int, int)=&pFun
}
面试题解析
题目一
int main()
{
int arr[] = { 1,2,3,4,5 };
printf("%d\n", sizeof(arr));//20 sizeof(数组名)计算的整个数组的空间字节
printf("%d\n", sizeof(arr+0));//4,当arr做加减运算时,我们把数组名看成了首地址,arr+0=&arr[9]
printf("%d\n", sizeof(*arr));//4 相当于取出首地址内存储的内容并计算其字节大小
printf("%d\n", sizeof(arr+1));//4
printf("%d\n", sizeof(arr[1]));//4
printf("%d\n", sizeof(&arr));//4/8 &arr是数组地址,所以求的是数组地址的大小
printf("%d\n", sizeof(*&arr));//20 &arr是数组地址 *&arr是将整个数组取出并计算大小
printf("%d\n", sizeof(&arr+1));//4/8 &arr+1其实还是一个地址
printf("%d\n", sizeof(&arr[0]));//4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8
return 0;
}
题目二
char arr[] = {'a','b','c','d'};
printf("%d\n",sizeof(arr));//4
printf("%d\n", sizeof(arr+0));//1
printf("%d\n", sizeof(*arr));//1
printf("%d\n", sizeof(arr[1]));//1
printf("%d\n", sizeof(&arr));//4/8
printf("%d\n", sizeof(&arr+1));//4/8
printf("%d\n", sizeof(&arr[0]+1));//4/8
题目三
char arr[] = {'a','b','c','d'};
//strlen()函数接收的是字符串的地址,只认地址,并计算 以传入地址为始,以\0的上一个地址为终,始终地址存放的字符长度
printf("%d\n",strlen(arr));//随机值,因为stelen计算字符串长度是找到\0之前的,没找到\0就随机值
printf("%d\n", strlen(arr+0));//随机值
// printf("%d\n", strlen(*arr));//实际上传入了一个字符‘a’,a的ASCII码是97,相当于把97这个地址传入strlen,越界非法访问地址,会崩溃
// printf("%d\n", strlen(arr[1]));//崩溃
printf("%d\n", strlen(&arr));//随机值
printf("%d\n", strlen(&arr+1));//随机值,但和上一行一定相差4
printf("%d\n", strlen(&arr[0]+1));//随机值,比之前的少1
return 0;