主页链接: LSR的主页
专栏链接: 《C语言》
文章目录
前言
以下是指针的最后内容。
一、函数指针变量
1.类型
int (*pf3) (int x, int y)
pf3指向函数的参数类型和个数的交代
pf3为函数指针变量名
pf3指向函数的返回类型
,其中x,y可以省略:
int(*pf3)(int, int)
int ( * ) (int x, int y) //pf3函数指针变量的类型
可以类比数组和指针之间的关系:
int arr[10] = {0}
int (*pa)[10] = &arr
2.使用
#include<stdio.h>
int Add(int x, int y)
{
return x+y;
}
int main()
{
int (*pf3)(int, int) = Add;
printf("%d\n", (*pf3)(2,3));
printf("%d\n", pf(3, 5));
return 0;
}
输出结果:
5
8
3.刻薄代码
(*(void(*)())0)()
void(*)() —— 函数指针类型定义
(void(*)())0 —— 强制类型转换
(*(void(*)())0)() —— 调用函数(或)((void(*)())0)();
void(*signal(int, void(*)(int)))(int)
signal(int, void(*)(int)) → 说明signal是一个函数,它的参数有两个:
第一个参数:int
第二个参数:void(*)(int)
剩余部分void(*)(int)就是signal的返回值类型
4.typedef关键字
typedef用来类型的重命名,可以将复杂的类型简单化。
typedef unsigned int unit;
//将unsigned int重命名为unit
//指针类型:将int* 重命名为ptr_t
typedef int* ptr_t;
//数组指针类型:将int (*)[5] 重命名为 parr_t
typedef int (*)[5] parr_t;
//函数指针类型:将void (*)(int)重命名为pf_t
typedef voud(*pf_t)(int)//新的类型名必须在*的右边
//简化第二个刻薄代码
typedef void(*p)(int)
p signal(int, p)
二、函数指针数组
定义:
int(*parr1[3])();
parr1先与[]结合,说明parr1是数组,数组内容是什么呢?
是int (*)()类型的函数指针。
三、转移表
函数指针数组的用途:转移表
1.实现加减乘除
#include<stdio.h>
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 (*pf1)(int, int) = Add;
int (*parr[4/*可以省略*/])(int,int)= {Add, Sub, Mul, Div};
//8 4
//简单演示
int i = 0;
for(i = 0;i < 4;i++)
{
int r = parr[i](8, 4);
printf("%d\n", r);
}
return 0;
}
2.实现加减乘除
2.1 一般实现
#include<stdio.h>
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;
}
void menu()
{
printf("*****************************\n");
printf("*******1. add 2. sub*******\n");
printf("*******3. mul 4. div********\n");
printf("******* 0. exit ************\n");
printf("*****************************\n");
}
int main()
{
int x = 0;
int y = 0;
int z = 0;
int input = 0;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch(input)
{
case 1:
printf("请输入两个操作数\n");
scanf("%d %d", &x, &y);
z = Add(x, y)
printf("%d\n", z);
break;
case 2:
printf("请输入两个操作数\n");
scanf("%d %d", &x, &y);
z = Sub(x, y)
printf("%d\n", z);
break;
case 3:
printf("请输入两个操作数\n");
scanf("%d %d", &x, &y);
z = Mul(x, y)
printf("%d\n", z);
break;
case 4:
printf("请输入两个操作数\n");
scanf("%d %d", &x, &y);
z = Mul(x, y)
printf("%d\n", z);
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,请重新选择\n");
break;
}
}while(input);
return 0;
}
2.2使用函数指针数组实现:
#include<stdio.h>
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;
}
void menu()
{
printf("*****************************\n");
printf("*******1. add 2. sub*******\n");
printf("*******3. mul 4. div********\n");
printf("******* 0. exit ************\n");
printf("*****************************\n");
}
int main()
{
int x = 0;
int y = 0;
int z = 0;
int input = 0;
int (*p[5])(int x, int y) = {0, add, sub, mul, div};//转移表
do
{
menu();
printf("请选择:");
scanf("%d", &input);
if(input<= 4 &&input>= 1)
{
z = (*p[input])(x, y);
printf("%d\n", z);
}
else if(input ==0)
{
printf("退出计算器\n");
}
else
{
printf("输入有误,请重新输入!!!\n");
}
}
}while(input);
return 0;
}
2.3回调函数实现
#include<stdio.h>
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;
}
void menu()
{
printf("*****************************\n");
printf("*******1. add 2. sub*******\n");
printf("*******3. mul 4. div********\n");
printf("******* 0. exit ************\n");
printf("*****************************\n");
}
void calc(int (*p)(int, int))
{
int x = 0;
int y = 0;
int z = 0;
printf("请输入两个操作数\n");
scanf("%d %d", &x, &y);
z = p(x, y);
printf("%d\n", z);
}
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;
}
三、qsort使用及模拟实现
使用头文件:stdlib.h,底层采用快速排序可以排序任意类型的数据。基本形式:
void qsort(void* base,//指针,指向的是待排序的数组的第一个元素
size_t num,//指向待排序数元素的个数
size_t size,//base指向的待排序数单个元素的大小(字节)
int (*compar)(const void*, const void*)//函数指针,指向两个元素比较的函数
);
1.排序整形数据
//使用qsort排序整型数据
//比较函数
//使用比较函数的注意点:相比较的
/*两个元素p1, p2,
前 > 后,返回一个 > 0的数
= ,返回0
< ,返回一个 < 0的数
返回>0的数就交换
返回<=0的数就不变*/
#incldue<stdio.h>
int int_cmp(const void* p1, const void* p2)
{
return *(int*)p1 - *(int*)p2;
}
void print(int*arr, int sz)
{
int i = 0;
for(i = 0;i<sz;i++)
printf("%d ", arr[i]);
printf("\n");
}
int main()
{
int arr[] = {1, 3, 5 ,9, 2, 4, 6, 8, 0};
int sz = sizeof(arr)/sizeof(arr[0]);
qsort(arr, sz, sizeof(int), int_cmp);
print(arr, sz);
return 0;
}
2.排序结构数据
////结构体补充
////三种指向结构体成员的方式
// ->间接访问操作符
// 结构图指针->成员名
//
//
//
// struct Stu
//{
// char name[20];
// int age;
//};
//
//void print(struct Stu* ps)
//{
// /*printf("%s %d\n", (*ps).name,(*ps).age);*/
// printf("%s %d", ps->name, ps->age);
//}
//int main()
//{
// struct Stu s = {"zhangsan", 19};
// /*printf("%s %d\n", s.name, s.age);*/
// print(&s);
// return 0;
//}
////创建变量:
//struct Stu
//{
// char name[20];
// int age;
//}s,s1;//通过类型创建的变量名
//
//typedef struct Stu
//{
// char name[20];
// int age;
//}stu;//修改的类型名
#include<stdio.h>
//使用qsort排序结构数据
struct Stu
{
char name[20];
int age;
};
//按照年龄来比较
int cmp_stu_by_age(const void* e1, const void* e2)
{
return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;
}
void test2()
{
struct Stu arr[] = { {"zhangsan", 18},{"lisi", 29}, {"wangwu", 37} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_age);
}
//按照名字来比较
int cmp_stu_by_name(const void* e3, const void* e4)
{
return strcmp(((struct Stu*)e3)->name, ((struct Stu*)e4)->name);//原理:按照对应的字符串中
//的ASCII码值比较的
//如: a b q > a b c d e
//和qsort比较函数返回规则一致
}
void test3()
{
struct Stu arr[] = { {"zhangsan", 18},{"lisi", 29}, {"wangwu", 37} };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_stu_by_name);
}
int main()
{
test2();
test3();
return 0;
}
3.qsort函数的模拟实现
使用回调函数,采用冒泡方式,模拟实现qsort
//采用冒泡方式模拟实现qsort函数
int int_cmp(const void* p1, const void* p2)
{
return *(int*)p1 - *(int*)p2;
}
void _swap(void* p1, void* p2,int size)
{
int i = 0;
for (i = 0; i < size; i++)
{
char tmp = *((char*)p1 + i);
*((char*)p1 + i) = *((char*)p2 + i);
*((char*)p2 + i) = tmp;
}
}
bubble(void* base, int count, int size, int(*int_cmp)(void*, void*))
{
int i = 0;
int j = 0;
for (i = 0; i < count - 1; i++)//有sz个元素,进行sz-1次循环
{
for (j = 0; j <count-1-i ; j++)//每次循环进行sz-1-i次比较
{
if (int_cmp((char*)base+j*size , (char*)base+(j+1)*size) > 0)
{
_swap((char*)base + j * size, (char*)base + (j + 1) * size,size);
}
}
}
}
int main()
{
int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble(arr, sz, sizeof(arr[0]), int_cmp);
print(arr, sz);
return 0;
}
四、sizeof和strlen的对比
1. sizeof
- sizeof是操作符不是函数,虽然有(),但是求变量的内存大小可以省略(),如:sizeof(a) == sizeof a;
- sizeof计算操作数所占内存大小,单位是字节;
- 不关注内存所放的数据是什么
- 数组名的理解:
数组首元素的地址
but两个意外:
1.sizeof(数组名):数组名表示整个数组,计算整个数
组大小,单位是字节
2.&数组名:数组名表示整个数组,取出的是整个数组的地址
注意:地址的大小始终为4/8个字节
2. strlen
- strlen是库函数,需包含头文件string.h;
- strlen是求字符串长度的,统计的是\0之前字符的各个数,单位字节
- 关注内存中是否有\0,如果没有,那就会往后一直找,可能会越界。
2346

被折叠的 条评论
为什么被折叠?



