目录
字符指针变量
在指针的类型中我们知道有⼀种指针类型为字符指针char*
p指向了a的地址解引⽤拿到了w然后打印
来自剑指offer笔试题
我们可以看到str1和str2的内容一样但是空间不一样,所以走else。
str3和str4的空间是一样的走if,因为str3和str4的内容是一样的编译器会把str4的空间指向str3的空间,所以空间是一样的
数组指针
数组指针是一个指向数组的指针
数组指针初始化就是取地址给数组指针就可以了
int(*p)[10]
如果不加()的话p会和[10]结合就不是指针了,所以要加()。
下面这代码,int是指向的数组的类型,(*p)说明p是一个指针,[10]是指向的数组有10个元素,&arr是整个数组
⼆维数组传参的本质
下面这代码就是把二维数组传参给⼀个add函数,让add来实现打印
⼆维数组传参本质上也是传递了地址,传递的是第⼀
⾏这个⼀维数组的地址。
在二维数组中也可以理解为多个一维数组
那么形参也是可以写成指针形式的
函数指针
函数指针是用来存放函数地址的,未来可以通过地址调用函数
那么函数是否有地址呢
我们做个测试:
我们可以看到函数是有地址的
函数指针创建
函数指针变量的写法其实和数组指针⾮常类似
可以写成&arr也可以不写都是等价的
函数指针的使用
这2个打印方式都是可以的p( 5 , 6) 编译器会变成(*p)(5 , 6)
两段有趣的代码
( * ( void ( * ) ( ) ) 0 ) ( );
这个代码是把0强制类型转换成函数指针,0也是一个函数指针,只不过没有返回值
void (*signal(int , void(*)(int)))(int);
void ( * signal ( int , void ( * ) ( int ) ) ) ( int );
void(其实这里就是变)(int)
typedef关键字
typede是用来类型重命名的,可以将复杂的类型,简单化
我们可以看到下面这个代码,把无符号的整型重命名为u_int
unsigned int 写起来不⽅便,如果重命名成 u_int 就⽅便多了
但是对于数组指针和函数指针稍微有些区别
数组指针
我们要将int(*)[10]重命名为arr我们可以写成这样
函数指针
我们要将int(*)(int ,int)函数指针重命名为ahh我们可以这样写
函数指针数组
我们要将int(* [10])(int ,int)重命名为att我们可以这样写
函数指针数组
把函数的地址存放到数组里,那这个数组就叫函数指针数组
我们可以通过下标来访问函数地址并且传参数过去
//打印菜单
void day()
{
printf("***************************\n");
printf("*** 1.加法 2.减法 ****\n");
printf("*** 3.乘法 4.除法 ****\n");
printf("***************************\n");
}
//加法
int add(int x, int y)
{
return x + y;
}
//减法
int add1(int x, int y)
{
return x - y;
}
//乘法
int add2(int x, int y)
{
return x * y;
}
//除法
int add3(int x, int y)
{
return x / y;
}
int main()
{
int a = 0;
int b = 0;
int f = 0;
do
{
//打印菜单
day();
// 0 1 2 3 4
int (*arr[5])(int, int) = { 0,add,add1,add2,add3 };
//用来访问函数指针数组的下标
scanf("%d", &f);
printf("请输入2个数值:");
//用来传参给函数
scanf("%d %d", &a, &b);
// 通过下标访问然后传参
printf("%d\n", arr[f](a, b));
} while (f);
return 0;
}
转移表
下面这代码是一个计算器,我们可以发现switch里有很多重复的,
还有当我们需要计算%,&,|,<< , >>这些的话要一个一个添加,我们就会发现代码非常重复很多的printf , scanf
void day()
{
printf("***************************\n");
printf("*** 1.加法 2.减法 ****\n");
printf("*** 3.乘法 4.除法 ****\n");
printf("***************************\n");
}
//加法
int add(int x,int y)
{
return x + y;
}
//减法
int add1(int x, int y)
{
return x - y;
}
//乘法
int add2(int x, int y)
{
return x * y;
}
//除法
int add3(int x, int y)
{
return x / y;
}
int main()
{
int a = 0;
int b = 0;
int r = 0;
do
{
day();
scanf("%d", &a);
switch (a)
{case 1:
printf("请输入2个数值:");
scanf("%d %d", &a,&b);
r = add(a,b);
printf("%d\n", r);
break;
case 2:
printf("请输入2个数值:");
scanf("%d %d", &a, &b);
r = add1(a, b);
printf("%d\n", r);
break;
case 3:
printf("请输入2个数值:");
scanf("%d %d", &a, &b);
r = add2(a, b);
printf("%d\n", r);
break;
case 4:
printf("请输入2个数值:");
scanf("%d %d", &a, &b);
r = add3(a, b);
printf("%d\n", r);
break;
default:
break;
}
} while (a);
}
我们可以使用函数指针数组的形式来访问这些函数
这样就没有那么多重复的内容了
我们要添加%,&,|,<< , >>的话也就只用添加计算函数和函数指针数组里的函数名
//打印菜单
void day()
{
printf("***************************\n");
printf("*** 1.加法 2.减法 ****\n");
printf("*** 3.乘法 4.除法 ****\n");
printf("***************************\n");
}
//加法
int add(int x, int y)
{
return x + y;
}
//减法
int add1(int x, int y)
{
return x - y;
}
//乘法
int add2(int x, int y)
{
return x * y;
}
//除法
int add3(int x, int y)
{
return x / y;
}
int main()
{
int a = 0;
int b = 0;
int f = 0;
do
{
//打印菜单
day();
// 0 1 2 3 4
int (*arr[5])(int, int) = { 0,add,add1,add2,add3 };
//用来访问函数指针数组的下标
scanf("%d", &f);
printf("请输入2个数值:");
//用来传参给函数
scanf("%d %d", &a, &b);
// 通过下标访问然后传参
printf("%d\n", arr[f](a, b));
} while (f);
return 0;
}
还有一种方法就是通过arr函数把要计算的函数传过去,int(*p)(int ,int)函数指针接收地址。
这个函数指针存放着计算函数的地址,我们就可以通过p来把参数传过去
//打印菜单
void day()
{
printf("***************************\n");
printf("*** 1.加法 2.减法 ****\n");
printf("*** 3.乘法 4.除法 ****\n");
printf("***************************\n");
}
//加法
int add(int x, int y)
{
return x + y;
}
//减法
int add1(int x, int y)
{
return x - y;
}
//乘法
int add2(int x, int y)
{
return x * y;
}
//除法
int add3(int x, int y)
{
return x / y;
}
int arr(int(*p)(int, int))
{
int a = 0;
int b = 0;
int r = 0;
printf("请输入2个数值:");
scanf("%d %d", &a, &b);
r = p(a, b);
printf("%d\n", r);
}
int main()
{
int f = 0;
do
{
day();
scanf("%d", &f);
switch ( f)
{
case 1:
arr(add);
break;
case 2:
arr(add1);
break;
case 3:
arr(add2);
break;
case 4:
arr(add);
break;
default:
break;
}
} while (f);
}