数组指针
是指针,是一种指向数组的指针。存放的数组的地址
数组名和&数组名
&数组名代表的是整个数组的地址,数组名除了放在&和sizeof内部,其余时候都是代表数组首元素地址
数组指针的用途
用于表示二维数组的数组名
二维数组要理解为多个一维数组集合,所以二维数组的首元素地址是第一行的一维数组的地址,相当于&arr。
函数指针
指向函数的指针
函数名等价于&函数名
有趣的两段代码
代码1
(*(void (*)())0)();
- 将0强制类型转换为函数指针
- 然后解引用找到强制类型转换后的指针对应的函数
- 对函数进行调用
代码2
void (*signal(int , void(*)(int)))(int);
- 返回值是一个函数指针的函数声明
- 可以试试用typedef去对类型重命名
用函数指针数组模拟一个计算器
指向函数指针数组的指针
#include<stdio.h>
void mune()
{
printf("*************\n");
printf("**1.Add******\n");
printf("**2.Sub******\n");
printf("**3.Mut******\n");
printf("**4.chu******\n");
printf("**0.exit*****\n");
printf("*************\n");
}
int Add(int x, int y)
{
printf("%d\n", x + y);
return x + y;
}
int Sub(int x, int y)
{
printf("%d\n", x - y);
return x - y;
}
int chu(int x, int y)
{
printf("%d\n", x / y);
return x / y;
}
int Mut(int x, int y)
{
printf("%d\n", x * y);
return x * y;
}
int main()
{
int input = 0;
int x, y;
int (*pf[5])(int, int) = { NULL,Add,Sub,Mut,chu };
do {
mune();
printf("请选择计算方式\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入计算数\n");
scanf("%d %d", &x, &y);
pf[input](x, y);
break;
case 2:
printf("请输入计算数\n");
scanf("%d %d", &x, &y);
pf[input](x, y);
break;
case 3:
printf("请输入计算数\n");
scanf("%d %d", &x, &y);
pf[input](x, y);
break;
case 4:
printf("请输入计算数\n");
scanf("%d %d", &x, &y);
pf[input](x, y);
break;
case 0:
printf("退出计算");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
回调函数
通过传递函数指针来调用别的函数的时候,被调用的该函数就是回调函数
通过回调函数来改进计算器
#include<stdio.h>
void mune()
{
printf("*************\n");
printf("**1.Add******\n");
printf("**2.Sub******\n");
printf("**3.Mut******\n");
printf("**4.chu******\n");
printf("**0.exit*****\n");
printf("*************\n");
}
int Add(int x, int y)
{
printf("%d\n", x + y);
return x + y;
}
int Sub(int x, int y)
{
printf("%d\n", x - y);
return x - y;
}
int chu(int x, int y)
{
printf("%d\n", x / y);
return x / y;
}
int Mut(int x, int y)
{
printf("%d\n", x * y);
return x * y;
}
void center(int i, int (*(*pf)[5])(int, int))
{
int x = 0, y = 0;
if (i > 0 && i < 5)
{
printf("请输入计算的数字:>\n");
scanf("%d %d", &x, &y);
(*pf)[i](x, y);
}
else if (i == 0)
{
printf("退出成功!\n");
}
else
{
printf("选择错误,请重新选择\n");
}
}
int main()
{
int input = 0;
int x, y;
int (*pf[5])(int, int) = { NULL,Add,Sub,Mut,chu };
do {
mune();
printf("请选择计算方式\n");
scanf("%d", &input);
center(input, &pf);
} while (input);
return 0;
}
qsort函数
参数为(void* 指向第一个要排序的元素 size_t待排序的元素个数 size_t 每个元素的大小 函数指针 指向一个函数用于规定比较方式)
int compare(const void p1,const void p2);
void*的指针不能直接解引用,因为这相当于一种无具体类型的指针,可以接收所有类型的指针,不能直接解引用,也不能++/--,使用时要强制类型转换
例1:用qsort来排序整型,结构体
例2:用冒泡排序实现通用效果
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student
{
int age;
char name[10];
};
int compint(const void* p1, const void* p2)
{
return *((int*)p1) - *((int*)p2);
}
int comp_struct_name(const void* p1, const void* p2)
{
return strcmp(((struct student*)p1)->name, ((struct student*)p2)->name);
}
void swap(const void* p1, const void* p2,size_t width)
{
for (size_t i = 0; i < width; i++)
{
char tmp;
tmp = *((char*)p1);
*((char*)p1) = *((char*)p2);
*((char*)p2) = tmp;
((char*)p1)++;
((char*)p2)++;
}
}
void bublle_sort(void*base,size_t num,size_t width, int(*com)(const void* p1, const void* p2))
{
size_t i = 0;
for (i = 0; i < num - 1; i++)
{
for (size_t j = 0; j < num - 1 - i; j++)
{
if (com((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)
int arr[] = { 23,6,432,9,60,8 };
size_t width = sizeof(arr[0]);
size_t num = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < num; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//qsort(arr, num, width, compint);
bublle_sort(arr, num, width, compint);
for (size_t i = 0; i < num; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
//qsort的使用(struct)
struct student s1[3] = { {15,"cc"},{18,"bb"},{25,"aa"} };
for (size_t i = 0; i < 3; i++)
{
printf("%s ", (&s1[i])->name);
}
printf("\n");
//qsort(s1, 3, sizeof(s1[0]), comp_struct_name);
bublle_sort(s1, 3, sizeof(s1[0]), comp_struct_name);
for (int i = 0; i < 3; i++)
{
printf("%s ", (&s1[i])->name);
}
//用冒泡排序去模拟一个这样通用的排序函数
return 0;
}