目录
前言
关于指针我们知道,
1.指针是一个变量,用来存放地址,地址唯一识别一块内存空间。
2.指针的大小是4个字节或8个字节。
3.指针有类型,指针的类型决定啦它解引用时的权限
一、指针的类型
1.字符指针
2.数组指针
3.指针数组
4.函数指针
5.函数指针数组
6.指向函数指针数组的指针
7.回调函数
二、不同类型指针的介绍
2.1字符指针
字符指针类型我们用char *来表示,这里我们必需知道字符指针放的其实是地址
例:
#include <stdio.h>
int main()
{
char str1[] = "hello.";
char str2[] = "hello.";
const char *str3 = "hello.";
const char *str4 = "hello.";
if(str1 ==str2)
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");
if(str3 ==str4)
printf("str3 and str4 are same\n");
else
printf("str3 and str4 are not same\n");
return 0;
}
str1和str2是两个不一样的字符串,所以地址也不会相同,在两者开始比较时,是比较的地址,所以不相同。
指针str3和str4是指针,存放的是地址,在此题中存放的都是hello.的首地址,首地址都是相同的,所以输出结果是same
2.2数组指针
顾名思义,数组指针就是指向数组的指针。本质上还是指针,指向的内容是数组。
数组指针是如何定义和使用的?
2.2.1如何创建数组指针
parr和*先结合说明parr指针变量,让后指向的是数组大小为10的整形数组;
*注:*parr[10],他们结合性不一样,parr和【10】的结合性比*和parr高,为啦准确表示数组指针我们必须要加括号。
我们来看一下arr的地址有&arr有何不同用法上有何不同。
我们注意到arr,&arr,parr地址都是相同的即数组首元素地址。
但是地址往下走的时候却不一样。
arr+1走一个整形大小;
&arr+1走的是整个数组的大小,直接到数组结尾;
parr+1走的也是是整个数组的大小,直接到数组结尾;
由此我们得出arr的地址是首元素地址;
&arr和parr是整个数组的地址;
2.2.2数组指针的使用
void print_arr(int(*arr)[5], int row, int col)
{
int i = 0;
for (i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
print_arr(arr, 3, 5);
return 0;
}
在二维数组中arr的地址不是首元素地址,而是第一行元素的地址。
所以我们在设置参数时应当设置成数组指针,即int(*arr)[5];
我们在输出时,按照二维指针的写法就行。
2.3指针数组
指针数组的定义:存放指针的数组
2.3.1如何创建指针数组
int *arr[3]
整形指针数组,这里强调arr与【3】的结合性更强
2.3.2如何使用指针数组
这里arr里面存放的是三个字符串的地址,并不是字符串本身,解引用时,我们可以用*,当然也可以使用数组的方式。
我们应当把指针数组*arr[3]与数组指针(*arr)[3]区分开,我们可以用结合性的方法来区分,看它先跟谁结合,
第一个它先跟【】结合所以它本质时数组,即指针数组, 第二个它先跟*结合所以本质是指针,即数组指针。
2.4函数指针
函数指针:指向函数的指针。 int (*p)()
p先于*结合代表它是指针,然后与()结合代表它是函数指针,同样需要参数时,我们可以往里面放参数类型,最后返回值时int型。
函数指针里放的是函数的地址,数组名其实也是函数的地址,区别在于函数指针可以放不同的函数地址,而函数只能不同的参数。
2.4.1函数指针的使用
这里我们可以使用p直接来调用函数,也可以用*p来调用函数,输出的结果都是函数的结果。
例题
// 代码 1( * ( void ( * )()) 0 )();
第一个代码,我们要逐层分析,紫色层代表强制类型转化,蓝色层代表0为指针,黄色层代表函数名为0的函数指针。
2.5函数指针数组
函数指针数组:指向函数的指针的数组,,本质为数组,数组元素为指针,指针指向函数。
int (*p[10])();这里p先和【10】进行结合,即代表本质为数组,然后和*结合代表它是指针,后面的括号说它是函数指针数组。
2.5.1函数指针数组的使用
这里是一个加减乘除计算器的代码:整数的加减乘除计算器 · 风夏/C语言进阶 - 码云 - 开源中国 (gitee.com)
#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 <= 4 && input >= 1))
{
printf( "输入操作数:" );
scanf( "%d %d", &x, &y);
ret = (*p[input])(x, y);
}
else
printf( "输入有误\n" );
printf( "ret = %d\n", ret);
}
return 0; }
其中它(如图)为函数指针数组,数组元素为0,add,sub,mul,div.
当我们使用这个数组时,只需改变参数即可。如图
2.6指向函数指针数组的指针
定义:指向函数指针数组的指针。本质为指针,指向的内容为函数指针数组。
2.6.1使用
我们把上题计算器中一些代码更改即变为指向函数指针数组的指针。
2.7回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针作为作为参数传递给另一个函数,当这个指针被用来其所指的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是当特定的事件或条件发生时由另一方调用的,用于对该事件或条件进行相应。
这里我们使用快速排序qsort,来说明回调函数。
在这个实例中qsort就是通过指针,来调用int_cmp,同时int_cmp是作为qsort函数参数的存在。
总结
这里共讲述啦7种函数指针的类型,即字符指针、数组指针、指针数组、函数指针、函数指针数组、指向函数指针数组的指针、回调函数。
希望大家多多理解、学习,希望大家取得进步。