目次
1. 字符指针
2.指针数组
3.数组指针
3.1 数组指针的界说
3.2 &数组名VS数组名
3.3 数组指针的利用
4.数组参数、指针参数
4.1 一维数组传参
4.2 二维数组传参
4.3 一级指针传参
5.函数指针
6.函数指针数组
7.指向函数指针数组的指针
8.回调函数
我们在开端学习C语言时,就已经开端的打仗过指针这个东西的存在,也对指针有了大概的相识
1.指针就是个变量,是用来存放内存地点的,内存中地点唯一标识一块内存空间!
2.指针的巨细是固定的4/8个字节(32位体系平台/64位体系平台)
3.指针是有具体范例的,指针的范例决定了在 + / - 整数时指针所偏移的步长(或称跨度), 以及指针解引用时访问多少个字节的权限
4.可以用来指针运算
这一篇中,继续来探索新的指针更深入条理的主题
1. 字符指针
在初识指针之后都知道指针中有一种范例叫字符指针 - char*;
对于指针一样寻常的利用:
int main() { char ch = 'W';//创建char变量ch char* pc = &ch; //取出变量ch的内存地址,将其放进字符指针变量pc中,pc的内容就是ch的地址 *pc = 'A';//通过指针解引用找到ch 将其内容值修改 return 0; } 复制代码
对字符指针另有一种利用:
int mian() { char* pc = "hello word";//一个思考,这是把一个字符串给放到pc指针中去了吗? printf("%s\n", pc); return 0; } 复制代码
第二个代码块中,char* pc = "hello word"; 是特殊容易让各人以为是把一个字符串hello word放到字符指针pc中去了,但是实在这个代码本质上只是把 hello word 首字符 h 的地点放到了pc中
来看一道风趣的标题
#include <stdio.h> int main() { char str1[] = "hello word"; char str2[] = "hello word"; char* str3 = "hello word"; char* str4 = "hello word"; 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 and str2 are same /str3 and str4 are not same 但实在,结果却大大相反!! 先看看结果
这里终极输出的是:
应该会有许多人很惊讶, 为什么str1 和str2是不相称的?
实在很简单,str1和str2 两个是数组,数组中存储的字符串 是一样的,但是各人不要忘记了,数组名代表数组首元素地点,既然是两个数组那么肯定就拥有着两块差别的空间,固然存储的内容一样,但是它们的地点 那但是完全不一样,下面的判断语句则是地点与地点是否相称,很显然 输出的结果肯定是else
那如果按这么说,那么str3为什么会和str4相称? 是由于str3和str4它们不是数组,它们是指针变量,只不外指向的是同一个字符串hello word,那么这个字符串是常量字符串,常量字符串的特性:可以访问,可以利用,但不可修改 那么既然都不可修改 内存中就没须要存储两份千篇划一的常量字符串,那么str3和str4 存储的都是这一个常量字符串中h的地点 颠末if语句判断 输出的结果为 same~
2.指针数组
在开端熟悉指针中,也学习了一下指针数组,指针数组本质上就是一个用于存放多个同范例指针聚集的数组
int* arr1[10]; //整形指针的数组 char* arr2[4]; //一级字符指针的数组 char** arr3[5];//二级字符指针的数组 复制代码
指针数组利用起来还好坏常简单的:
int main() { //int* arr1[10]; //整形指针的数组 //char* arr2[4]; //一级字符指针的数组 //char** arr3[5];//二级字符指针的数组 //创建三个数组 int a[] = { 1,2,3,4,5 }; int b[] = { 6,7,8,9,10 }; int c[] = { 11,12,13,14,15 }; //创建指针数组 并且把存进三个数组的指针 int* tmp[3] = { a,b,c }; //利用指针数组,打印这三个指针指向的空间内容 int i = 0; for (i = 0; i < 3; i++) { int j = 0; for (j = 0; j < 5; j++) { printf("%d ", * (tmp[i] + j));//写法1; //printf("%d ", *(*(tmp + i) + j));//写法2; //printf("%d ", tmp[i][j]);//写法3; } printf("\n"); } return 0; } 复制代码
在这段代码中,我创建了3个int范例数组,而且都存储5个元素
再而创建了一个指针数组,用于存放这三个数组的指针,那么在之前的学习中我们都知道,数组名代表着首元素的地点,那么既然代表着首元素的地点,它就是个地点 地点实在就是指针,也就可以明白为数组名实在就是一个一级指针, 创建指针数组时 tmp先和[ ]联合,代表它是个数组,数组中有3个元素,每个元素范例为int* 足以证实它是个指针数组,那么再把三个数组的数组名放进去,实在存放的就是三个一级指针
在下面的打印中,printf实在有三种写法,第一种写法中 tmp实在等价于*(tmp+i)拿到了tmp数组中某个指针指向的那块空间,然后在表面又举行了 +j 解引用 就是拿到了谁人位置的元素 将其打印 这也就等价于写法2: *(*(tmp + i) + j 写法2又等价于写法3:tmp[j]
3.数组指针
3.1 数组指针的界说
数组指针到底是指针?照旧数组?
答案是:指针.
我们已经熟悉:
整形指针: int * pint; 可以大概指向整形数据的指针。
浮点型指针: float * pf; 可以大概指向浮点型数据的指针。
那数组指针应该是:可以大概指向数组的指针。
下面代码哪个是数组指针?
int *p1[10]; int (*p2)[10]; //p1, p2分别是什么? 复制代码
表明:
int *p1[10]; 在我们学过的优先级中,[ ]的优先级是高于*的 以是p1先和[ ]联合,这时间p1是个数组,它有10个元素,每个元素的范例是int* 以是它是个指针数组!
int (*p)[10] ; 这里 ( )的优先级是最高的,那么p先和*举行联合,这时间p是个指针, 把p拿掉后还剩下 int [10]; 证实指针指向一个数组,数组有10个元素,每个元素是int范例;
//这里要留意: [ ] 的优先级是要高于*的,以是必须加上( )来包管p先和*联合.
3.2 &数组名VS数组名
对于下面的数组:
复制代码
arr 和 &arr 分别是什么?
此中,arr是数组名,数组名表现的是首元素的地点.
那&arr数组名到底是什么? 看一段代码:
#include <stdio.h> int main() { int arr[10] = {0}; printf("%p\n", arr); printf("%p\n", &arr); return 0; } 复制代码
运行结果如下:
可见数组名和&数组名打印的地点是一样的。
岂非两个是一样的吗?
我们再看一段代码:
#include <stdio.h> int main() { int arr[10] = { 0 }; printf("arr = %p\n", arr); printf("&arr= %p\n", &arr); printf("arr+1 = %p\n", arr+1); printf("&arr+1= %p\n", &arr+1); return 0; } 复制代码
它的运行结果如下
根据上面的代码我们发现,实在&arr和arr,固然值是一样的,但是意义应该不一样的。
现实上: &arr 表现的是数组的地点,而不是数组首元素的地点。
数组的地点+1,跳过整个数组的巨细,以是 &arr+1 相对于 &arr 的差值是40
3.3 数组指针的利用
那数组指针是怎么利用的呢?
既然数组指针指向的是数组,那数组指针中存放的应该是数组的地点。
看代码:
#include <stdio.h> int main() { int arr[10] = {1,2,3,4,5,6,7,8,9,0}; int (*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p //但是我们一般很少这样写代码 return 0; } 复制代码
为什么我说一样寻常很少如许写代码? 由于数组指针用在一维数组上,实在并不是那么得当, 最得当一维数组的指针,就是一级指针,而非数组指针,不信的话 看看下面代码数组指针对于一维数组的打印:
#include <stdio.h> int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,0 }; int(*p)[10] = &arr;//把数组arr的地址赋值给数组指针变量p int* a = arr; //把数组首元素地址付给一级整形指针a; int i = 0; for (i = 0; i < 10; i++) { printf("%d ", *((*p) + i));//数组指针打印一维数组的方式 printf("%d ", *(a + i));//一级指针打印一维数组的方式 } return 0; } 复制代码
在这段代码中,显着用一级指针来举行一维数组打印,岂论是誊写,照旧可读性 都会更加的好,用数组指针也是可以,只不外显得有点杀鸡焉用牛刀 一样寻常数组指针,都是用于二维数组身上
一个数组指针的利用:
[code]#include void print_arr1(int arr[3][5], int row, int col) { int i = 0; for(i=0; i