一、指针和一维数组
先通过一组实例来了解一下,会更加形象。
#include<iostream>
using namespace std;
int main()
{
int a[5]={1,2,3,4,5};
for(int i=0;i<5;i++)
cout<<"a["<<i<<"]"<<"的地址为:"<<&a[i]<<endl;
cout<<" &a:"<<&a<<'\n';
cout<<" a:"<<a<<'\n';
cout<<" &a[0]:"<<&a[0]<<endl;
cout<<" a[0]:"<<a[0]<<endl;
return 0;}
输出结果为:
a[0]的地址为:0x70fdf0
a[1]的地址为:0x70fdf4
a[2]的地址为:0x70fdf8
a[3]的地址为:0x70fdfc
a[4]的地址为:0x70fe00
&a:0x70fdf0
a:0x70fdf0
&a[0]:0x70fdf0
a[0]:1
通过比较可以看出,在数值上a,&a,&a[0]是相等的 ,但还是有区别的,要清楚它们各表示什么,才能更好的理解后面的知识
&a:当数组名a表示取整个数组的地址时,书写时这样表示“&数组名”(&a)
下面这个和上面的要区别一下,因为说法很相似,重点放在书写形式上,这样会更好理解
a或&a【0】:当数组名a表示数组首地址,同时也可以表示数组首元素的地址时,书写这样来“数组名”或“&a[0]”
而a[0]表示数组的首元素 ,相同a【2】=2;这和普通数组一样;
二、 数组指针与指针数组
举个栗子,更容易理解;
int (*p)[5];根据符号优先级 () > []> * ,所以先看()内的,而()里面是指针,*和p构成指针的定义,int修饰[]构成数组的定义,数组在这里并没有实际的变量名,可以看成是一个有虚拟的变量名 ;所以就表示定义了一个指针p指向一个含有5个元素的一维数组(即数组指针) 通俗的讲:这个数组里面存储的元素都是地址,地址,地址,
比如:int *p【5】,里面存放1,2,3,等等int类型的数,而int (*p)【5】存放的是 1,2,3等等数的地址
#include<iostream>
#include<iomanip>//调用setw()函数要用到此函数库,下面会详细解释的
using namespace std;
int main()
{
int a[3]={2,3,4},(*p1)[3]=&a,*p2;//定义了一个一维数组a,一个指向数组a的指针p1,一个野指针(不知道指向哪里)
p2=&a[2];//把a[2]的地址赋p2
cout<<setw(4)<<"p1:"<<p1<<endl;//setw函数用作设置输出的域宽(即长度),数字4表示长度。该函数只对紧接着的输出有效,紧接着的输出结束后又变回默认的域宽(即长度)
cout<<setw(4)<<"*p1:"<<p1<<endl;
cout<<setw(4)<<"p2:"<<p2<<endl;
cout<<setw(4)<<"*p2:"<<*p2;//输出结果为a[2]的值4
return 0;
}
//定义一个所有元素都为指针的数组(指针数组)
//int *p[3];//[]的优先级必*高,p与[]结合构成一个数组的定义,数组名为p
//int *修饰的是数组p的内容,即数组的每个元素(p[0],p[1],p[2])都是指针
运行结果为:
p1:0x70fdf0
*p1:0x70fdf0
p2:0x70fdf8
*p2:4
访问一维数组:
#include<iostream>
using namespace std;
int main()
{
int a[3]={1,2,3};
int (*p)[3]=&a; //这是数组指针,别看用了&,但是*p还是地址
cout<<"a:或&a[0]:"<<a<<endl;//0x22fe30
cout<<"&a:"<<&a<<endl;//0x22fe30
cout<<"p:"<<p<<"____"<<&a<<endl; //特意这么写,只写了一个&a的
cout<<"*p:"<<*p<<"____"<<a[0]<<endl; //相等
cout<<"*p+1:"<<*p+1<<"____"<<a[1]<<endl; //相等
cout<<"p+1:"<<p+1<<"____"<<&a[1]<<endl; //p+1的值更大
cout<<"尾地址的下一个地址:"<<&a[2]+1<<endl; //和p+1的数值相同
cout<<"和p+1的数值相同"<<endl;
return 0;
}
运行结果:
a:或&a[0]: 0x70fdf0
&a: 0x70fdf0
p: 0x70fdf0____0x70fdf0
*p: 0x70fdf0____1
*p+1: 0x70fdf4____2
p+1: 0x70fdfc____0x70fdf4
尾地址的下一个地址:0x70fdfc
为什么p+1比&a【1】大呢,后面再做解释
三、指针与二维数组
重点理解指针指向的是谁
include<iostream>
using namespace std;
int main()
{
int b[3][2]=//记主int 占4个字节,char占 1个字节
{{1,2},
{3,4},
{5,6}};
int (*p1d)[2]=b; //也可以写成(*p1d)[2]=&b[0],p1d为数组指针 ,指向首元素b[0]
cout<<"p1d:"<<p1d<<endl; //输出指向对象b[0]的地址,即&b[0]
cout<<"*p1d:"<<*p1d<<"等价于b[0]:"<<b[0]<<"等价于&b[0][0]:"<<&b[0][0]<<endl;
//*为解引用;p1d为b的首元素的地址,解引用p1d将得到其所指对象,即b[0],
//数组名b[0]表示首元素的地址,即等价于&b[0][0]
//b[0]与&b[0][0]都指向b[0][0]
cout<<"*p1d+1:"<<*p1d+1<<"等价于&b[0][0]+1:"<<&b[0][0]+1<<endl;
//*先与p1d结合构成解引用,得到的是b[0],等价替换一下,+1表示当前地址的下一个地址
//把二维数组b看成宿舍楼,有三层楼,每层有两个房间,可以画个图好理解些
//*p1d指的第一层楼,+1就网上加一层,来到第二层楼
cout<<"*(p1d+1):"<<*(p1d+1)<<"等价于&b[0]+1:"<<&b[0]+1<<endl;
//先解读圆括号内的,p1d+1指当前元素b[0]的下一个元素
cout<<"&b[1]:"<<&b[1]<<endl; //即为b[1]啦
return 0;
//a[0]表示首元素a[0][0]的首地址,a[0][0]的首地址
}
我所要讲的都在注释代码的注释里面,看代码,看注释,然后自己运行代码
四、指针与多维数组
以下给出一个三维数组c
#include<iostream>
using namespace std;
int main(){
int c[2][2][2]={1,2,3,4,5,6,7,8};
//空间立体来的,不太好表示,这里我就直接赋值了
cout<<"先来看第一个元素: "<<endl;
cout<<"&c"<<&c<<'\n';
cout<<"c[0]:"<<c[0];//平面,第一个元素
cout<<"=c[0][0]:"<<c[0][0]<<endl;//一行或一列,第一个元素里的第一个元素
cout<<"&c[0][0][0]:"<<&c[0][0][0]<<endl;
//有些只是数值相等,意义相差甚远
cout<<"现在看第二个元素:"<<endl;
cout<<&c;
cout<<"="<<c[1];//平面, 第二个元素
cout<<"="<<c[1][0]<<endl;//一行或一列,第二个元素里的第一个元素
cout<<&c[1][0][0]<<endl;
//对比结果即可很容易理解啦
}
运行结果: 先来看第一个元素:
&c 0x70fe00
c[0]:0x70fe00=c[0][0]:0x70fe00
&c[0][0][0]:0x70fe00
现在看第二个元素:
0x70fe00=0x70fe10=0x70fe10
0x70fe10
简单分析下,c[x][y][z]就是长方体一样,c[0][0][0]=1但是c[0][0]却表示地址,就跟一维数组一样,int a【5】={1,2,3,4,5};
a【1】=1,但是a却表示地址一样,和三维数组的表示方法一样,读者可以自行联想。