-
理解函数指针和定义
先看一下一段代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
void test()
{
printf("hehe\n");
}
int main()
{
printf("%p\n", test);
printf("%p\n", &test);
system("pause");
return 0;
}
输出的是两个地址,且是相同的,而此地址就是test函数的地址,那么同理就能使用指针来存储,那么函数指针又是怎么样的呢?
看下面代码:
#define _CRT_SECURE_NO_WARNINGS 1
void test()
{
printf("hehe\n");
}
int main()
{
void(*pfun1)();
}
pfun1可以存放,pfun1先和*结合,说明Pfun1是指针,指针指向的是一个函数,指向的函数无参数,返回类型是void。
-
理解函数指针数组和定义,转移表使用
函数指针数组,顾名思义就是把函数的地址存在一个数组当中,那么这个数组就是函数指针数组。
int(*parr1[10])();
parr1先和[]结合,说明parr1是数组,数组的内容是int(*)()类型的函数指针
函数指针数组的用途:转移表
例子:(原始计算器)
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.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 main()
{
int x, y;
int input = 1;
int ret = 0;
while (input)
{
printf("*************************\n");
printf(" *****1:Add 2:Sub *****\n");
printf(" *****3:Mul 4:Div *****\n");
printf("*************************\n");
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入操作符:>");
scanf("%d %d", &x, &y);
ret = Add(x, y);
break;
case 2:
printf("请输入操作符:>");
scanf("%d %d", &x, &y);
ret = Sub(x, y);
break;
case 3:
printf("请输入操作符:>");
scanf("%d %d", &x, &y);
ret = Mul(x, y);
break;
case 4:
printf("请输入操作符:>");
scanf("%d %d", &x, &y);
ret = Div(x, y);
break;
default:
printf("选择错误\n");
break;
}
printf("ret = %d\n", ret);
}
system("pause");
return 0;
}
(使用转移表之后的计算器)
#define _CRT_SECURE_NO_WARNINGS 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 main()
{
int x, y;
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 < 5 && input > 0))
{
printf("请输入操作符:>");
scanf("%d %d", &x, &y);
ret = (*p[input])(x, y);
}
else
printf("输入有误!\n");
printf("ret = %d\n", ret);
}
return 0;
}
-
理解指向函数指针数组的指针和定义
void test(const char* str)
{
printf("%s\n", str);
}
int main()
{
//函数指针 pfun
void(*pfun)(const char*) = test;
//函数指针的数组 pfunArr
void(*pfunArr[5])(const char* str);
pfunArr[0] = test;
//指向函数指针数组 pfunArr 的指针 ppfunArr
void(*(*ppfunArr)[10])(const char*) = &pfunArr;
return 0;
}
-
理解回调函数的使用
回调函数就是一个通过函数指针调用的函数,如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其他指向的函数时,我们就说这时回调函数,回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时又另一方调用的,用于该事件或条件进行响应。
例子:
练习使用qsort函数排序各种类型的数据以及模仿qsort的功能实现一个通用的冒泡排序。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
struct Stu
{
char name[20];
int age;
};
void print_arr(int *arr, size_t sz)
{
unsigned int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
int cmp_int(const void *e1, const void *e2)
{
return *(int *)e1 - *(int *)e2;
}
int cmp_stu_by_age(const void *e1, const void *e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
int cmp_stu_by_name(const void *e1, const void *e2)
{
return strcmp(((struct Stu*)e1)->name , ((struct Stu*)e2)->name);
}
int cmp_str(const void* e1, const void* e2)
{
return strcmp(*(char**)e1, *(char **)e2);
}
void _Swap(char *buf1, char *buf2, size_t width)
{
unsigned int i = 0;
assert(buf1&&buf2);
for (i = 0; i < width; i++)
{
char tmp = *buf1;
*buf1 = *buf2;
*buf2 = tmp;
buf1++;
buf2++;
}
}
void bubble_sort(void *base, int num, int width, int (*cmp)(const void*e1, const void*e2))
{
int i = 0;
int j = 0;
assert(base&&cmp);
for (i = 0; i < num - 1; i++)
{
for (j = 0; j < num - 1 - i; j++)
{
if (cmp((char*)base + j*width, (char*)base + (j + 1)*width)>0)
{
//交换
_Swap((char*)base + j*width, (char*)base + (j + 1)*width, width);
}
}
}
}
int main()
{
利用qsort测试整型排序
//int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
//int sz = sizeof(arr) / sizeof(arr[0]);
//qsort(arr, sz, sizeof(arr[0]), cmp_int);
//print_arr(arr, sz);
//
利用qsort测试结构体排序
//struct Stu arr[] = { { "zhangsan", 20 }, { "lisi", 15 }, { "wangwu", 8 } };
//int sz = sizeof(arr) / sizeof(arr[0]);
//qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
//qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
利用bubble_qsort测试结构体排序
//struct Stu arr[] = { { "zhangsan", 20 }, { "lisi", 15 }, { "wangwu", 8 } };
//int sz = sizeof(arr) / sizeof(arr[0]);
//bubble_sort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
利用bubble_qsort测试字符串排序
//char *arr[] = { "abcdef", "qqqqq", "bbbbbb" };
//int sz = sizeof(arr) / sizeof(arr[0]);
//bubble_sort(arr, sz, sizeof(arr[0]), cmp_str);
system("pause");
return 0;
}