指针的初等应用
函数的双向参数传递
自由访问数组
自由访问函数
高级应用
指针的复合
特殊应用
const指针
void指针
引用
数据的访问原理
内存的每个每个字节有一个自己的编号叫做地址,而相关的数据和代码会被储存在一段连续的内存内,因此我们可以通过访问首地址然后根据数据类型从而得到该数据的全部内容。
数据访问的两种方式
直接访问:将变量名映射到数据的地址,通过变量名访问
间接访问:将变量的地址存放在ing外一个内存单元中,我们从这个内存单元中取出它的地址,进而进行访问,而指针代表的就是地址的形象表达。(好处:当我们需要存储大量数据的时候我们可以只存储首个地址,然后进行访问,花费就只有一个指针的内存,而直接访问需要对每个点数据开点)
指针变量是一个存储内存地址的变量
//指针的定义
int *p
//指针的赋值,int告诉我们接下来的内容需要按照int来理解(知道变量类型以推出大小)
int i;
i=5;
//相当于开辟了一个变量名为i,存储内容为5的内存单元
int *p;
p=&i;
//&i相当于是对i的一个引用,也可以看作是一种取地址的运算符,p存储了i的内存地址
cout<<*p<<endl;
//输出为5
//*p是对p存储内存地址的访问,*也可以看作一个运算符,用于对地址的访问
//指针修改变量
*p=11
cout<<i<<endl;
//输出为11
//*p允许用来改变p地址保存的内容
int *p p指向的内存单元存放了一个整数
double *p p指向的内存单元存放了一个双精度浮点数
void *p 无类型指针(空指针),该类型指针可用来只考虑指向,不考虑类型,类似于java当中多态性的obj类,可以指向任何类
空指针可直接存储数据的地址,但是当我们想要访问地址的时候我们需要提前告知所存储的数据类型
int a=3;
void *p1;
p1=&a;
cout<<(int*)p1;//语法逻辑都正确
cout<<(float*)p1;//语法正确逻辑错误
输出内容:
值得一提的点
当我们并没有事先声明一个变量名用来存储镶银的内容但是又想根据指针来保存某个内容那么我们可以尝试使用new int(x)的方式来开辟一个内存存储x对应的内容。当我们用int连续定义几个变量的时候他们的内存空间事实上是相邻的,但是使用new int(x)开辟的地址是存储在heap里面,也就是与之前的几个变量名存储的空间并不连续。(补充一下,地址的分配是由)
常见的一些错误
int *p;
*p=10;
//p还没有指向内存地址就修改内存地址的值
int *p1=0x2000
//c++中不支持指向一个未知区域
指针的应用一:函数参数的双向传递
void swap(int *p,int *q)
{
int *c;
c=p;
p=q;
q=c;
return ;
//可以传入相关变量的指针,直接对内存地址进行修改,从而达到函数内对函数外的变量进行修改。
//内外一致的一种操作
}
指针应用二:自由访问数组
数组在内存中占据一段连续的单元,通过首地址+偏移量可以访问到每个元素。
c++规定:数组名就是数组的起始地址,同时也是执政,也是0号元素的地址。
实际中通常额外引入一个新的指针变量p,通过++,在数组上面游走。(其实从这里来看,一些特殊数据结构的迭代器,使用++的方式来遍历数据结构就非常的合理)
int a[10],*p;
p=a;
或者也可以是p=&a[0];
可以通过p++指向下一个整数,但是不可以a++
原因:数组名a是常量指针,只可以指向数组首地址
而且p[5]等价于a[5],支持本质相同的访问和修改
因此,这样的代码看起来就十分合理了(在下是菜鸟,之前学算法竞赛看这个感觉一点也不合理)但是如果
p=a+1
p[1]=a[2]
可以一开始对p有一定的偏移量
char a[100];
string x;
x=a;
c++规定,可以通过指针引用数组元素,即a[i]可以理解为*(a+i)等价可以推出赋值,访问等其他相关操作。
学c++的经典操作,*p++。
int a[5]={5,4,3,2,1};
int *p=a;
cout<<*p++;
遍历a当中的元素
后置的++/--比*优先级要搞,*p++等价于*(p++)
其作用相当于就是一个迭代器,去除当前指向的元素,指针指向下一个相当于x=scan.nextInt();
但是值得注意的是p++是一个后加,所以应该是先取出p所指向的内容然后指向下一个