函数指针、数组指针的理解
数组指针
函数指针
函数指针数组
函数指针数组的指针
回调函数
qsort函数排序
数组指针
介绍数组指针之前,我们先考虑一个问题----数组指针是指针还是数组?
答案是指针。
定义:数组指针是指向数组的指针,数组指针中存放的是数组的地址。
数组指针的使用:
#include<stdio.h>
#include<windows.h>
#include<assert.h>
#define ROW 2
#define COL 3
void print_arr1(int arr[2][3], int row,int col)
{
assert(arr);
int i = 0;
int j = 0;
for (;i< row; i++)
{
for (j=0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
}
printf("\n");
}
void print_arr2(int (*arr)[3], int row, int col)
{
assert(arr);
int i = 0;
int j = 0;
for (; i < row; i++)
{
for (j=0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
}
printf("\n");
}
int main()
{
int arr[ROW][COL] = { {1,2,3},{4,5,6} };
print_arr1(arr,ROW,COL);
print_arr2(arr, ROW, COL);
system("pause");
return 0;
}
由此代码可知,无论是几维数组在传参时均会降维为指向其内部元素类型的指针。二维数组传参时临时变量为数组指针,可省略靠近数组名[]里的数字,其余均不可省略;二维数组的首元素是二维数组的第一行。
函数指针
为什么要有函数指针?
扫描二维码关注公众号,回复:
4356567 查看本文章
原因是函数也是代码,也是有地址的,函数名/取地址函数名代表其入口地址。
#include<stdio.h>
#include<windows.h>
#include<assert.h>
void test()
{
;
}
int main()
{
test();
printf("%p\n", test);
printf("%p\n", &test);
system("pause");
return 0;
}
定义:是保存函数地址的指针。(4个字节)
void (*test)();//函数指针
函数指针数组
定义:存放函数指针的数组就叫函数指针数组。
void (*test[])();//函数指针数组
函数指针数组的使用:转移表(计算器)
//一般做法
#include<stdio.h>
#include<windows.h>
//#include<assert.h>
void menu()
{
printf("**************************\n");
printf("****欢迎来到计算器页面****\n");
printf("**** 1.add 2.mul *****\n");
printf("*****3.sub 4.div1 *****\n");
printf("*****0.exit *****\n");
printf("**************************\n");
}
int add(int x, int y)
{
return x + y;
}
int mul(int x, int y)
{
return x * y;
}
int sub(int x, int y)
{
return x - y;
}
int div1(int x, int y)
{
return x / y;
}
int main()
{
int n = 1;
menu();
while (n)
{
printf("请输入选项:\n");
scanf("%d", &n);
int x = 0, y = 0;
/*printf("请输入两个整数!\n");
scanf("%d%d", &x, &y);*/
//若将两个数字输入放在此处会出现输入错误时不能退出系统,而是显示“输入两个整数”的提示
switch (n)
{
case 1:
printf("请输入两个整数!\n");
scanf("%d%d", &x, &y);
printf("%d\n", add(x, y));
break;
case 2:
printf("请输入两个整数!\n");
scanf("%d%d", &x, &y);
printf("%d\n", mul(x, y));
break;
case 3:
printf("请输入两个整数!\n");
scanf("%d%d", &x, &y);
printf("%d\n", sub(x, y));
break;
case 4:
printf("请输入两个整数!\n");
scanf("%d%d", &x, &y);
printf("%d\n", div1(x, y));
break;
case 0:
printf("退出计算器!\n");
break;
default:
printf("输入错误,请重新输入!\n");
}
}
}
//使用函数指针数组解决计算器问题
#include<stdio.h>
#include<windows.h>
//#include<assert.h>
void menu()
{
printf("**************************\n");
printf("****欢迎来到计算器页面****\n");
printf("**** 1.add 2.mul *****\n");
printf("*****3.sub 4.div1 *****\n");
printf("*****0.exit *****\n");
printf("**************************\n");
}
int add(int x, int y)
{
return x + y;
}
int mul(int x, int y)
{
return x * y;
}
int sub(int x, int y)
{
return x - y;
}
int div1(int x, int y)
{
return x / y;
}
int main()
{
int n = 1;
menu();
while (n)
{
printf("请输入选项:\n");
scanf("%d", &n);
int(*arr[5])() = { 0,add,mul,sub,div1 };//转移表
//定义一个函数指针数组,存放函数地址
if (n >= 0 && n < 5)
{
int x = 0, y = 0;
printf("请输入两个整数:>\n");
scanf("%d%d", &x, &y);
printf("%d\n", (*arr[n])(x,y));//输出结果
}
else
{
printf("输入有误,请重新输入!\n");
scanf("%d", &n);
}
}
system("pause");
return 0;
}
两种方法相比而言,一般方法代码相似度较高,有大量冗余代码;用函数指针数组能减少代码冗余,代码看起来更简洁直观,提高运行速率。
函数指针数组的指针
定义:是指向函数指针数组的指针,数组的元素是函数指针。
void (*(*test)[]))();//函数指针数组的指针
回调函数
定义:回调函数就是一个通过函数指针调用的函数。回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用,用于对该事件或条件进行响应。
qsort排序整形数组(冒泡排序)
#include<stdio.h>
#include<windows.h>
#include<assert.h>
int MathCom(const void *x, const void *y)//回调函数MathCom比较相邻元素大小
{
assert(x);
assert(y);
int *x_ = (int *)x;
int *y_ = (int *)y;
if (*x_ > *y_)
{
return 1;
}
else if (*x_ < *y_)
{
return -1;
}
else
{
return 0;
}
}
void DisplayArr(int arr[], int sz)//打印数组
{
assert(arr);
int i = 0;
for (; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1,4,5,6,958,67,-2,56,3 };
int sz = sizeof(arr) / sizeof(arr[0]);
printf("排序前:");
DisplayArr(arr, sz);
qsort(arr, sz, sizeof(int), MathCom);
printf("排序后:");
DisplayArr(arr, sz);
system("pause");
return 0;
}
qsort排序字符串
#include<stdio.h>
#include<windows.h>
#include<stdlib.h> //qsort头文件
#include<search.h> //qsort头文件
#include<assert.h>
int StringCom(const void *x_, const void *y_)
{
assert(x_);
assert(y_);
char **x = (char **)x_; // 原数组为char *的数组,其地址为char **类型
char **y = (char **)y_;
return strcmp(*x, *y);
}
int main()
{
char* arr[] = { "dddd","fff","bb","aaaa" };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(char*), StringCom);
int i = 0;
for (; i < sz; i++)
{
printf("%s\n", arr[i]);
}
system("pause");
return 0;
}