本篇文章,我们将一起探讨指针高级版
一、指针数组、数组指针
1.1 指针数组
就是存放指针的数组,因此指针数组是一个数组,不是指针
例如:
int* pa[5]; //整型指针的数组
char* pb[2]; //字符型指针的数组
int** pc[3]; //二级整型指针的数组
1.2 数组指针
意为指向数组的指针
例如:
int(*pa)[5]; //指向整型数组的指针
char(*pb)[3]; //指向字符型数组的指针
这里其实就是pa先和“ * ”结合,因为“ [ ] ”他的优先级高于“ * ”
那么下面这个是数组还是指针?
int* (*pa)[3];
一步一步来看,( *pa )是一个指针,这个指针指向一个数组( * pa ) [ 3 ],这个数组的类型为int*
所以他是一个指向 int* 型数组的指针
1.3 数组名和&数组名
上面讲述了指向数组的指针,那么他接收的是什么呢?
例如:
以下打码打印出的结果是什么?
int main()
{
int arr[5] = { 1,2,3,4,5 };
printf("%p\n", arr);
printf("%p\n", &arr);
return 0;
}
这里可以看出arr和&arr打印的地址都是一样的,那么他两的意思是一样的吗?
int main()
{
int arr[5] = { 1,2,3,4,5 };
printf("%p\n", arr + 1);
printf("%p\n", &arr + 1);
return 0;
}
我们打印+1以后的结果来看一下
这里他俩的结果就不一样了
原因是arr是数组的首元素的地址,而&arr是整个数组的地址,因此arr + 1跳过4个字节,而&arr + 1跳过的是5 * 4 = 20个字节
二、 函数指针
2.1 函数指针的定义
函数指针就是指向函数的指针
例如:
void test()
{
int arr[5] = { 1,2,3,4,5 };
printf("%p\n", arr + 1);
printf("%p\n", &arr + 1);
}
int main()
{
void (*pf)() = test;
(*pf)();
return 0;
}
因此可以看出,函数指针的定义为:
void (*pfun1)( );
2.2 函数指针数组
就是一个存放了函数指针的数组
定义为:
void (*pf[5])( ) = { 0 };
2.3 函数指针数组的应用
合理运用函数指针数组可以帮我们简化很多代码,例如计算器的实现:
void menu()
{
printf("********************************\n");
printf("***** 1.add 2.sub *****\n");
printf("***** 3.mul 4.div *****\n");
printf("***** 0.exit *****\n");
printf("********************************\n");
}
//加
int add(int x, int y)
{
return x + y;
}
//减
int sub(int x, int y)
{
return x - y;
}
//乘
int mul(int x, int y)
{
return x * y;
}
//除
int div(int x, int y)
{
return x / y;
}
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("请输入两个操作数:");
scanf("%d %d", &x, &y);
ret = add(x, y);
printf("%d\n", ret);
break;
case 2:
printf("请输入两个操作数:");
scanf("%d %d", &x, &y);
ret = sub(x, y);
printf("%d\n", ret);
break;
case 3:
printf("请输入两个操作数:");
scanf("%d %d", &x, &y);
ret = mul(x, y);
printf("%d\n", ret);
break;
case 4:
printf("请输入两个操作数:");
scanf("%d %d", &x, &y);
ret = div(x, y);
printf("%d\n", ret);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
上面这个计算器的代码是不是略显繁琐
这里我们就可以运用函数指针数组将上面的加减乘除的函数装起来
//函数指针数组
int(*pf[5])(int, int) = { NULL,add,sub, mul,div };
int main()
{
int input = 0;
int x = 0;
int y = 0;
int ret = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
if (input >= 1 && input <= 4)
{
printf("请输入两个操作数:");
scanf("%d %d", &x, &y);
ret = (*pf[input])(x, y);
printf("%d\n", ret);
}
else if (input == 0)
{
printf("退出计算器\n");
break;
}
else
{
printf("输入错误\n");
}
} while (input);
return 0;
}
这样代码就简化了很多
三、回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
例如上述计算器的函数还可以简化为:
void calc (int(*pf)(int, int))
{
int x = 0;
int y = 0;
int ret = 0;
printf("请输入两个操作数:");
scanf("%d %d", &x, &y);
ret = pf(x, y);
printf("%d\n", ret);
}
int main()
{
int input = 0;
do
{
menu();
printf("请输入:");
scanf("%d", &input);
switch (input)
{
case 1:
calc(add);
break;
case 2:
calc(sub);
break;
case 3:
calc(mul);
break;
case 4:
calc(div);
break;
case 0:
printf("退出计算器\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
return 0;
}
这样的代码是不是更简化了
3.1 回调函数的应用
回调函数还有个典型的运用例子,qsort( )函数的调用,qsort可以对任何类型的变量进行排序。话不多说,直接上代码
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1) - (*(int*)e2);
}
int main()
{
int arr[10] = { 5,2,4,3,6,8,9,7,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr,sz,sizeof(int),cmp_int);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
也可以自己写一个练习一下
int cmp_int(const void* e1, const void* e2)
{
return (*(int*)e1) - (*(int*)e2);
}
void swap(char* e1, char* e2, size_t width)
{
size_t i = 0;
for (i = 0; i < width; i++)
{
char tmp = *(e1 + i);
*(e1 + i) = *(e2 + i);
*(e2 + i) = tmp;
}
}
void new_qsort(const void* base, size_t sz, size_t width, int(*pf)(const void*e1, const void*e2))
{
size_t i = 0;
for (i = 0; i < sz - 1; i++)
{
size_t j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
if (pf((char*)base + j * width,(char*)base + (j + 1) * width) > 0)
{
//交换
swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
}
}
}
}
int main()
{
int arr[10] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
new_qsort(arr,sz,sizeof(int),cmp_int);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
本章内容就到这里, 下一期我们说说常见的指针题型
标签:arr,int,void,C语言,plus,数组,printf,指针 From: https://blog.csdn.net/m0_74779094/article/details/142612039