2

【c语言进阶】如此清晰的指针讲解让你再也不怕学不会指针了,硬核指针讲解。

 2 years ago
source link: https://blog.csdn.net/ai15013602354/article/details/120598083
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

🎇前言🎇

在学习c语言中,很多人都觉得指针是一个难点。而同时指针在c语言中又是非常重要的工具,如果不能熟练的掌握指针,c语言的学习是不完整的,本篇文章总结了大家在深入学习指针时所需要掌握的知识。

目录

🎇前言🎇

💎指针初阶内容回顾💎

 💎字符指针💎

✨数组指针和指针数组✨

数组指针

指针数组

区分数组指针和指针数组

✨数组传参与指针传参✨

数组的传参

指针的传参

 ✨函数指针✨

⚖函数指针数组✨

✨回调函数的概念✨



💎指针初阶内容回顾💎

1. 指针就是个变量,用来存放地址,地址唯一标识一块内存空间。
2. 指针的大小是固定的4/8个字节(32位平台/64位平台)。
3. 指针是有类型,指针的类型决定了指针的+-整数的步长,指针解引用操作的时候的权限。
4. 指针的运算


 💎字符指针💎

字符指针是一种常见的指针,一般用 char* 来表示:

下面来介绍字符指针的两种常见的使用方法:

 一:用来存放字符变量的地址

 二:存放常量字符串的地址

 请大家思考一个问题此时指针变量p中存放的是什么?是这个常量字符串?还是这个常量字符串的地址?还是这个常量字符串首元素的地址?

很多人第一次见这种字符指针使用方式时,都会下意识的误认p指针存放的是这个常量字符串,但这种想法显然不成立,因为指针的作用是储存地址的,而把常量字符串赋值给指针,指针其实拿到的是这个常量字符串首元素的地址。

由上面的讲述,现在我来考虑这样一个经典的问题:

运行结果是这样的:

这到底是为什么呢?

原因是:我们用这个常量字符串去开辟两个数组时,实际上开辟了两块不同的内存空间,而这个常量字符串本身是存储在内存中的静态区,因此我们拿出它的地址赋值给两个指针时,拿到的是同一块内存空间。


✨数组指针和指针数组✨

现在我们来介绍并区分一组概念:数组指针和指针数组

首先大家思考一个问题:数组指针是数组还是指针呢?

答案是:数组指针是指针,是指向数组的指针。

下面来学习数组指针的定义初始化与使用。

 从结果上可以清晰的看出来,两个地址差值是40,刚好是整个数组的空间大小。

在这里出现了一个新朋友 &arr ,下面我们来解释一下 &arr 和arr到底有什么区别。

&数组名和数组名的区别

1:&数组名:这里的数组名代表的是整个数组,所以这句代码的意思是取出整个数组的地址。

2:数组名一般被认为是首元素的地址

补充:数组名什么情况下表示整个数组,什么情况下表示首元素的地址

1:数组名代表整个数组:只有&数组名和sizeof(数组名)即数组名单独放在sizeof的内部。

2:除了上面两种情况,其它所有情况都数组名表示首元素的地址。


在大家前面的学习中想必已经了解过整型数组,字符数组,浮点型数组等多种数组。

我们把元素类型是指针的数组称为指针数组。

下面举例介绍指针数组的使用


区分数组指针和指针数组

请大家分辨以下三个变量的类型

1:int *parr1[10];
2:int (*parr2)[10];
3:int (*parr3[10])[5];

给出答案:1:parr1首先与[]结合,说明它是个数组,数组有10个元素每个元素是一个一级整型指针。指针数组

2:parr2首先与*号结合,说明它是一个指针,该指针指向一个有10个元素且每个元素均为整型的数组。数组指针

3:parr3先和[]结合,说明它是一个有10个元素的数组,其中每个元素都是指向一个有5个元素且每个元素均为整型的数组。存放数组指针的数组


✨数组传参与指针传参✨

大家可能有想过为什么c语言要存在指针?现在给出其中重要的一个原因。

在函数传参的时候,如果采用传值调用,则需要对实参进行拷贝,如果在实参所占空间很大时,这时对实参进行一次拷贝,就会浪费大量的栈区空间。而若我们进行传址调用,只需要把实参的地址传递上去,并不需要对实参进行拷贝,而且地址只占用(4/8)个字节的空间,节省了空间。

一般结构体传参的时候,用传址调用更好。


数组的传参

在这里我以二维数组传参作为例子

注意:二维数组的数组名在表示首元素的地址时,代表的是第一行的地址,也就是说二维数组的每一个元素是它的每一行

指针的传参

在这里我们以一级指针传参为例

1:一级指针的传值调用:对于指针的传值调用是用同级的指针接收,例如一级指针传参用一级指针接收,二级指针传参用二级指针接收。

2:一级指针的传址调用:对于指针的传址调用是用下一级的指针接收的,例如一级指针传参用二级指针接收。

 在这里就不得不讨论传值调用和传址调用的区别了。

详细内容请看这篇文章:函数


 ✨函数指针✨

从字面意思大家就可以知道函数指针其实是一种指针,是指向函数的指针。

函数指针储存的是函数的地址:请大家分析下面这个例子

从中大家可以清晰的看出来,函数也是有地址的,且以上两种方式都可以打印出函数的地址。

我们知道函数的地址存放在函数指针中,那么函数指针具体是怎样使用的呢?


⚖函数指针数组✨

相信经过前面的学习,大家应该能分辨清楚函数指针数组是什么意思了。

函数指针数组顾名思义就是一个数组,它的每一个元素都是一个函数指针。

函数指针数组的用途是:转移表

现在我们可以利用函数指针数组实现一个简易的计算器:

在这里我只给出代码:


✨回调函数的概念✨

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

回调函数顾名思义就是把函数作为参数传递给函数,在函数参数部分用函数指针来接收,在函数内部通过函数指针来调用函数时,我们将这个函数称为回调函数。

回调函数的应用十分广,只要涉及到将函数作为参数传递就可以使用回调函数。

下面留一个思考题:对于库函数qsort而言,我们在使用它的时候需要传递一个比较函数作为比较器,请大家写用于整型比较的比较器,用于字符比较的比较器,用于结构体中某个成员的比较器等等,你想比较什么就写什么比较器。

大家能不能自己编写一个函数模拟实现qsort呢?

答案会在下期揭晓。


以上代码,还可做优化在此仅作参考,若有更好的算法,还望能够私信告知,多谢各位。

由于本人水平十分有限,若有错误请即使告知!如果有帮助别忘了,万分感谢。

点赞👍         收藏✨    关注✌


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK