指针的深入理解

指针的深入理解

我不是一个指针大师,也没有什么独到见解,写这个纯粹为了应付考试,所以大佬可以自行跳过
下面进入正文:
如果现在不知道指针是什么的好兄弟可以看看我以前写的一篇博文:
指针的初级理解
现在是进阶:
1.1通过指针引用数组
为什么可以用指针来引用数组呢?不知道的快去看上面的文展,里面第一段我就聊了聊数据的储存。
数组本身就是一种储存数据的方式,相比于你直接定义n个变量2.a,b,c,d…,直接定义数组s[n]的好处就是s[n]中储存的每个元素的地址都是有规律的。
比如s[0]的地址是2000,那么我保证s[1]的地址一定是2004(s[]是int类型的,默认int类型占4个字节)
所以这个性质就保证了我可以利用指针来对数组进行一系列的操作。
1.2 数组指针的加减运算
加减运算很好理解,这里就补充几个要注意的东西:

  1. ‘++’ 和 ‘ * ’的优先级是一样的,在计算机内遵守的是从右向左的计算方式,所以如果你写的代码是:*p++其等价于 *(p++),在实际运用运用应该避免第一种写法,容易出错。(其实我从没用过指针
  2. 有c++基础的好兄弟一定多次运用过sort函数
sort(s,s+n);
或者sort(s+1,s+n+1);

在之前我聊sort的时候提到过,sort函数的参数实际上是数组的地址,比如说s就是指s[0]的地址而s+n就是指s[n]的地址。
那么肯定有小伙伴有这种想法:那可不可以通过改变s的值来改变所指向的值呢?
这样想只能说too young to simple .
再品品,如果可以直接改变地址的值,那还要定义指针干啥?
那么直接引出结论:数组s[0]的地址是一个指针常量,他在程序中是永恒不变的,就比如旅店1234是指厕所,旅店1235是总统套房,那么可以通过改变门牌号来改变房间本质吗?把旅店1234改为旅店1235后厕所就变总统套房了吗?显然矛盾。
1.3 用数组名作为函数参数

#include
using namespace std;
void find(int a[],int n)
{
	for(int i=0;i<n;i++)
	cout<<a[i]<<' ';
	cout<<endl;
}
int main()
{
	int s[10],n;
	cin>>n;
	for(int i=0;i<n;i++)
	cin>>s[i];
	find(s,n);
	return 0;
}

这个部分说简单点就是
s[3]=* (p+3)
说复杂点就是int a[ ] =int * a,在主函数中find(s,n)中的s表示的是s[0]的地址,所以通过地址来实现数组的全局化。
我不知道这样聊对不对,没听过课,如果有所不足请指正
1.4 通过指针引用多维数组
数组这东西以我蒟蒻的眼光看就是一个连续的地址,无论是一维还是二维,其实就是一段空间。简单来说,无论是几维数组,其本质就可以当成一维数组来看,将一维数组进行折叠就可以增加维度。
就比如s[3][2] 他的展开就可以当成s[6]。
回归一下主题,那么指针怎么在引用多维数组呢?
直接引用书中内容:
如果要表示s[1],则写成*(s+1),如果要表示s[1][1],则写成 * ( *(s+1)+1)。
如果我们用之前学过的东西分析一波这个操作:
首先 *(s+1)s表示的是地址,那么s+1也应该是地址,又用上了指针运算符,所以 * (s+1)表示的应该是一个值,一个s+1地址所指的值。再继续分析,直接逻辑爆炸,这写的都是啥啊?
为了解释这个,我认为可以直接看代码运行结果:

#include
using namespace std;
int main()
{
	int f[3];
	f[0]=1;
	f[1]=2;
	f[2]=3;
	int s[3][2];
	s[0][0]=1;
	s[0][1]=2;
	s[1][0]=3;
	s[1][1]=4;
	
	cout<<*(f+1)<<endl;
	cout<<*(s+1)<<endl;
	return 0;
}

这样聊吧,对于s[3][2]来说,s[1]指的是第一行第0列的地址,而s[1][0]指的是第一行第0列的值。而s+i表示的是第 i 行第0列的地址 ,* (s+1)+n表示的是第1行和第n列的地址。而如果要表示数组内容,就要再加一个*号,也就是**(s+1)。
那么知道了以上的点后,再聊聊 int(*p)[4]是指什么东西。
品品,int *p 表示的是定义一个指针变量,那么 int ( * p)[4]是不是可以理解成定义了一个指针数组呢?那么用书上的话来说就是指针变量p指向了包含4个整形元素的一维数组。用我的话来说就是p指向的是每一行第0列的地址。
什么意思呢?这样想吧,如果直接定义一个指针int * p,那么我们可以用p来指向每一个元素,但这样做毕竟太麻烦,你需要计算才能准确表达二维数组的某一行某一列的值。所以这时候牛犇就想简化一下代码,于是就诞生了int (*p)[3] 这种写法。
这里还要讲一个注意点:

s[][];
1find(s,n);
2find(*s,n);

1和 2 是不一样的,s作为一个二维数组,s表示的是s[0]的地址,而*s表示的是s[0][0]的地址。
所以要个一个参数为int (*p)[3]的子函数传参的话,只能用第一种,不能用第二种,虽然它们的数值一样,但它们的类型本质还是不一样的。
1.5 通过指针引用字符串
先分析一下这个代码

char *string ="l love china!"

string是一个字符类型的指针,他指向的内容是 I 的地址。看到这里有人就会问,为什么这个可以直接表示地址?不懂的快翻到开头,点开我给的超链接,我在那篇文章的开头就聊了计算机的内存。即“I love china”作为数据,他一定有自己的储存空间,有空间就有地址,所以可以通过字符型指针来指向它。
这一部分我看不下去了,有很多没讲,因为我觉得大部分和前面讲的相似
1.6 指向函数的指针
能够使用指针引用数组的原因是函数名代表函数的起始地址。
那么运用指针首先需要定义一个指针:
类型名 (*指针变量)(函数参数表列)
==int (*p) (int,int )
定义了之后就是赋予地址:
p=max (max是一个子函数的函数名)。
赋值了之后就要使用它。
直接(*p)(a,b)。
所以总结就是一句话:把函数名换为 * p就是指针调用函数。
1.7 指针数组和多重指针
指针数组,顾名思义就是指针构成的数组,其定义的方式如下:
int *p[4] 因为 * 和[ ] 的优先级是一样的,而运算方向是自右向左的,所以这样写相当于 先定义了一个数组p[4],然后定义这个数组是指针型数组。
指针数组的运用和数组运用无太大差异。
多重指针,即指向指针的指针。
举个例子,我定义了一个指针 p1 ,p1指向的地址是a的地址,那么问题来了,指针p1有没有地址呢?答案是肯定的,那么如果这时候我又定义了一个指针p2,p2指向的是p1 的地址,那么 a=**p1。
1.8 指针数组作main函数的形参
对不起,我也不会。
1.9 动态内存分配与指向它的指针
太累了,不想学了,下次再补充吧。

以上就是指针的主要内容,还有一些细枝末节,我不知道,也不想知道,毕竟我就是想过一过考试,如果好兄弟们想深度学习,就要自己努力了!

你可能感兴趣的:(学习,指针)