⭐️前言
指针,表面意思为指向某个东西的针。在c与c++中实际实际上是指向某个地址的变量,举个例子:
int i=0;
int *p=&i;
其中i是整型变量,p是整型指针变量。可以理解为指针就是同类型变量(当然,也有常量,下文提及)存储的是地址。
指针是个让人又爱💓又恨💔的东西。可爱是因为指针的应用范围特别广泛(我感觉是c中应用范围最广的),可恨是因为指针的学习难度(我感觉是c语言中最难的)。那么接下来我将为各位详细解读发表个人对指针的理解。本人能力有限,难免会出现错误,望大佬斧正。
一、一维指针
1.定义
一维指针我又称之为普通指针,原因很简单,他太普通了,普通到没有任何难点(1)。一维指针的定义规则很简单:类型匹配。即int 型对应int*,char型对应char*
int *a=NULL;
char *b=NULL;
float *c=NULL;
.
.
.
.
.
.
总之一维指针的定义只要掌握类型匹配即可(2)
ps:(1)一维指针可以定义指针数组,下文提及
(2)可以强制类型转换:
char s;
char *ss=&s;
int b=0;
(int *)ss=&b;
2.使用范围
(1)取地址
int i=0;
int *p=&i;
普通的取地址
(2)传参数
应用于函数与函数之间(分为传参与传址,此处为传址)
#include<stdio.h>
void cz(int *a){
*a=1;
return;
}
int main()
{
int b=2;
printf("%d\n",b);
cz(&b);
printf("%d",b);
return 0;
}
上面演示的就是指针传参数,在cz函数里的操作会使b的值发生改变,两个printf的输出分别是2和1,就是因为在函数中把b的值利用指针重新赋值为1。
(3)待补充
数据结构暂时不谈
二、行指针与列指针
1.行指针
(1)定义
行指针,是数组里特有的指针,是用来指向数组某一行的指针。行指针的作用主要是用来传参给其他函数(因为行指针与数组的首字母都是传的是地址,所以这里的传参其实就是传址)
int a[2][10];
int (*p)[10];
p=a;
以上就简单定义了一个行指针,其中p指向的是a[0]的地址,也就是数组a第一行的首地址。
不难理解p+1就是指向a[1]的地址,也就是数组a第二行的首地址。
(2)用法
行指针的用法其实挺容易理解的(个人感觉)。
1.p+n表示指向数组a第n行的首地址。
2.*(p+n)表示到第n行的首元素。(例:p=&a[0],*p=a[0])
3. *(p+n)+m表示具体到第n行第m个元素的地址。
4. *( *(p+n)+m)表示第n行第m个元素。(可以用来输出元素)
ps:前面所讲的某一行的首元素实际上是该一行数组的首地址,而某一行的首地址是指该一行数组的首地址的地址。
ps:其实p可以理解为二级指针(下文有讲)
2.列指针
列指针本身存在的意义就是为了更好的理解行指针,其实上文的*(p+n)+m就是列指针,就是指向某一列的指针(要在行指针前提下)。
ps:行指针涉及到的二维数组并不是矩阵那样,矩阵可以说行与列是同一等级的,而这里的二维数组行>列,必须先访问行才能访问列。其实行指针与指针数组和二维指针可以近似相等。
三、指针数组与二级指针
上文说过行指针与它两是近似相等的,那为什么不把他们三一起来讲?是因为我个人觉得行指针的定义方式与二级指针与指针数组有较大差别。而且行指针要比其他两个更容易理解。
1.定义
指针数组的定义
char *a[]={"zhangsan","19","Superivisor"};//(1)
char **p;//(2)
p=a;//(3)
(1)定义了一个指针数组并初始化。
(2)定义了一个二级指针。
(3)把指针数组赋值给二级指针
(2)用法
本质用法个人觉得二级指针与数组指针与行指针用法相同。
但在使用时有一些地方需要注意
1.指针数组可以初始化,但int型不行,个人理解如下:
指针数组中存放的是地址,准确来说是数组的首地址,而int型存在一个问题:无法判断初始化的值是数组还是元素,而且就算默认为数组也不能判断一个怎样划分给予的初始值。
2.二级指针无法直接像二维数组那样定义完就可以赋值,原因是二级指针定义是仅仅是定义并没有开辟空间,所以需要先给二级指针开辟空间,再进行赋值(指针数组或者其他二级指针给二级指针赋值时是连带着先按照其本身空间大小给二级指针分配了相同大小的空间)。另外注意要适时的给开辟空间的二级指针释放空间(开辟:malloc;释放:free());
四、待补充
五、总结
指针是学习c语言的一大难点,是一座无法跨越的大山,所以我们一个人要做的就是努力学会指针,搬开挡在学习路上的大山!😃