指针的介绍:
指针是一个用来存放地址的变量,可以通过指针存放的地址找到对应位置的值,对其进行使用。
指针在32位平台下的大小是4个字节,在64位平台下是8个字节。(这是因为32位平台下内存地址是由32根地址线组成,一根地址线就是1bit,用4个字节就可以存下,而64位平台有64根地址线,需要八个字节才可以存下)。
- 如果对指针进行加减与解引用操作,则±的步长与解引用操作的长度由指针类型决定,指针类型是几个字节±步长与解引用就是几个字节。
一、简单指针🌈
char* pc(字符指针)
int *pi(整形指针)
float* pf(浮点型指针)
还有short…double等等,拿部分举例。
1.1 指针的定义与使用
- 这三种指针的用法基本相同,只不过char*指针存放的是char变量地址,int型指针存放的是int变量地址,float指针存放的是float变量地址。
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> int main() { char a = 'a'; //定义一个char类型变量 char* pa = &a; //*号先与pa结合说明pa是一个指针类型,指向的是char型数据的地址,将a的地址给到pa *pa = 'b'; //通过pa改变a的值 printf("%c", a); // b int num = 10; int* pnum = # *pnum = 20; printf("%d", num); float f = 9.0; float* pf = &f; *pf = 5.0; printf("%d", f); }
我们可以使用指针对指针指向的变量进行使用(修改或输出)。
1.2 指针与数组
- 数组名就是数组的首地址。
代码示例
- 得到数组首地址可以通过指针遍历数组
代码示例
二、指针数组✨
指针数组就是用来装指针的数组
int p1[]; //(方便理解拿整形数组对比)p1与[]结合说明p1是数组,装的是int类型的数据 int* p2[]; //[]优先级比*高 p2先与[]结合,说明p2是一个数组 里面装的是int*类型的数据
举个例子
#include <stdio.h> int main() { int a = 0; int b = 0; int c = 0; int* arr[3] = {&a,&b,&c}; //指针数组就是数组的每个位置都存储一个地址(指针) }
三、数组指针🌞
3.1 数组指针的定义
数组指针与指针数组名字非常相似但是却截然不同,数组指针是一个指针,指针数组是一个数组
//对比一下指针数组和数组指针 int* pa[]; //这是指针数组,优先级问题,pa先与[]结合,说明pa是一个数组,装的是int*的数据 int (*pa)[] //这是数组指针,()优先级更高,pa先与*结合,说明pa是一个指针,指向一个int类型的数组
3.2 ”数组名“与”&数组名“
前面说了数组名代表数组首元素地址,那&数组名呢?
代码示例
- 对数组名与&数组名进行输出,发现地址一样
- 对数组名与&数组名+1,发现数组名加了四个字节,而&数组名加了十六进制的28,也就是十进制的40,为整个数组的大小。
结论:数组名与&数组名地址一样,但是数组名代表的是首元素地址,而&数组名代表的是整个数组。
3.3 数组指针使用
void print(int (*pa)[3]) { for(int i=0;i<2;i++) { for(int j=0;j<3;j++) { printf("%d",arr[i][j]); } } } int main() { int arr[2][3] = {0,1,2,3,4,5}; print(arr); //二维数组首地址相当于 &(第一个一维数组) }
四、函数指针🤓
函数指针就是指向函数的指针
- 函数指针的定义
- *函数返回值 (pa)(函数参数)
可以看作pa先与*结合,说明pa是个指针,指向一个函数
4.1函数指针的使用
代码示例
int add(int a,int b) { return a+b; } int main() { int (*pa)(int ,int) = add; int a = 3; int b = 4; printf("%d",pa(3,4)); //7 }
五、函数指针数组🚀
函数指针数组就是用来装函数指针的数组,需要注意每个函数指针数组的返回值和参数必须相同类型
- 函数指针数组的定义
- *函数返回值 (pa[])(函数参数)
可以看作pa先与[]结合说明pa是一个数组,每个位置装的是函数指针(地址)
5.1 函数指针数组的使用
#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; } void menu() { printf("***************\n"); printf(" 1:add 2:sub \n"); printf(" 3:mul 4:div \n"); printf(" 0:quit \n"); printf("**************\n"); } int main() { int x = 0; int y = 0; int input = 0; int ret = 0; int(*p[5])(int x, int y) = { NULL, add, sub, mul, div }; do { menu(); printf("请选择:"); scanf("%d", &input); if (input >= 1 && input <= 4) { printf("输入两个数字:"); scanf("%d %d", &x, &y); ret = (*p[input])(x, y); } else if (input == 0) { break; } else { printf("请输入0-4的数字\n"); continue; } printf("%d\n", ret); } while (input); }
六、指向函数指针数组的指针🚀🚀
函数指针数组的定义为 int (*pa[5])(参数),指向函数指针数组的指针就是:
int (( * pa)[5]) (参数) //用括号把pa括起来使得pa先与 * 结合,说明pa是一个指针,返回值类型就为函数指针数组
指向函数指针数组的指针的定义
void test(char* str) { printf("指针真简单,%s",str); } int main() { //定义一个函数指针数组 void (*pa[5])(char*) ; pa[0] = test; //指向函数指针数组的指针 void (*(*ppa)[5])(char*) = &pa; return 0; }
七、回调函数
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应 。
- stdlib头文件下的qsort()函数就是一个回调函数,链接: qsort函数详解
完结
创作不易,还请各位小伙伴多多点赞👍关注✨收藏⭐