由于个人在写关于字符串数组代码的时候,总会遇到一些关于字符串指针的问题,所以想把这些简单易混的知识点进行梳理
二维整型数组
int a[m][n]
其中m表示有多少行,n表示有多少列。
int main()
{
int a[2][2]= {1,2,3,4};
cout<<a[0]<<endl; //a[0]是二维数组,第0行的地址。
cout<<*a[0]<<endl; //*a[0]是第0行第一个元素
cout<<*a[0]+1<<endl; //*a[0]+1是第0行第二个元素
cout<<*a[0]+2<<endl; //*a[0]+2是第1行第1个元素,由于数组是线性存放于计算机地址中,所以第三个,也就是(1,1)位置的元素
cout<<*a[0]+3<<endl; //*a[0]+3是第1行第2个元素。
}
a[0]
数组的地址,如果你输出a[0],那么你得到只是一段地址。这个就是二维数组的首地址。
*a[0]
这个是a[0]地址的值,输出 * a[0], 结果是1。
*a[0]+1
这个是a[0]地址向后移动1位的位置的值,结果是 2.
*a[0]+2
这个是a[0]地址向后移动2位的位置的值,结果是 3
*a[0]+3
这个是a[0]地址向后移动2位的位置的值,结果是 4
【注释】:由于数组是按照地址线性排列在计算机中的,所以你脑海里的二维情形,只是你脑海中的,a[0]+2这个位置就是我们设计的两行两列数组中第2行第1个元素的位置了。
二维字符数组
char ch[m][n]
二维字符数组,其实是你看到的一维字符串数组。
m表示有多少个字符串,n表示每个字符数可以存放n-1个字符。(因为第n个位置,它要存放‘\0’用来标志字符串的结束)
int main()
{
char b[3][6]= {"Zhang","Jia","chen"};
cout<<b<<endl;
cout<<b+1<<endl;
cout<<*b<<endl;
cout<<b[0]<<endl;
cout<<b[1]<<endl;
cout<<b[2]<<endl;
}
b
在这里就是字符串数组的首地址,也就是字符串“zhang”的地址
b+1
在这里就是字符串"Jia"的地址
*b
就是取b地址的值,b是数组的首地址,所以 *b就是“Zhang”
b[0]
就是第一个字符串,也就是“Zhang”
b[1]
是第2个字符串,也就是“Jia”
b[2]
是第3个字符串,也就是“chen”
二维的数组我们简单介绍完毕,接下来我们介绍关于数组指针和指针数组的事情。
数组指针
int (*p)[n] p一个指针,指向一维整形数组,这是因为()的优先级高于[ ],所以()先与 *p结合构成指针,指向一维数组。
指针数组
int *p[n] p是一个数组,“ * ”与数组p[n]结合构成了一个含有n个指向整型元素的指针。
二维指针
int **pp 距离“int”最近的 ‘ * ’告诉我们它是一个指针,它指向的数据类型是 *pp(指针类型)。
假如 :
int a=3;
int *p;(或者int *p=a)
p=&a;(p是一个指针,它的值是地址,*p是p指向地址的值。&a表示a的地址。)
int **pp;
pp=p;(pp得到的是p的“地址”,*pp是p地址的值,p地址的“值”是a的地址,所以 **pp=*p也就是3)
现在我们再详细探讨关于数组指针和指针数组那点小破事
一、指针数组与字符串数组
int main()
{
char b[3][6]= {"Zhang","Jia","chen"};
char *p[3];
//char (*p1)[3];
*p=b[0]; //*p在这里等价于p[0],指针数组的首地址,指针数组的第一个指针指向了b[0]位置;
p[1]=b[1];//p[1]这个位置的指针,指向b[1]这个位置
cout<<*p<<endl;
cout<<p[0]<<endl;
cout<<*p+1<<endl; //p指针后移一位的值的第一个元素是h
//cout<<*(p+1)<
cout<<p[1]<<endl;
}
运行结果:
*p在这里等价于p[0],指针数组的首地址,指针数组的第一个指针指向了b[0]位置;
p[1]这个位置的指针,指向b[1]这个位置。
同理,你写一个p[2]=b[2];p[2]这个位置的指针,指向b[2]这个位置.
由于这里是指针数组,所以赋值与数组和数组元素赋值一样,要对应的一个一个赋值,不可以直接让p=b,因为这里的指针是存放在数组里面的。p[0]是一个指针,但p不是,p只是这个指针数组的数组首地址而已。
语句 cout<< *(p+1)报错的原因是因为p[1]的指针还没有给他赋值,她没有指向,也就不知道它指向的内容,所以报错
*p+1这个就相当于p指针从p[0]指向位置后移动了一位,所以打印的结果是“hang”
二、数组指针与字符串数组
int main()
{
//int a[2][2]= {1,2,3,4};
char b[3][6]= {"Zhang","Jia","chen"};
char (*p1)[6];//数组指针,指向数组的指针,记住指针指向数组的长度与字符串的长度保持一致
p1=b;
cout<<*p1<<endl;
cout<<p1[0]<<endl;
cout<<*p1+1<<endl; //p指针后移一位的值的第一个元素是h
cout<<*(p1+1)<<endl;
}
运行结果:
p1=b,数组b把首地址的值给了数组指针p1。现在指针p1开始指向数组b.
*p1与p1[0]都是p1在首地址位置的值。
*p1+1是指针p1从当前位置的值,向后移动一位。
*(p1+1)是指针p1挪动一个位置指向数组第二个位置。
三、二级指针与字符串数组
int main()
{
//int a[2][2]= {1,2,3,4};
char b[3][6]= {"Zhang","Jia","chen"};
char *p[6];//指针数组
char **pp;
p[0]=b[0];
p[1]=b[1];
p[2]=b[2];
pp=p ; //此时pp等于的是p的地址
cout<<*pp<<endl;
cout<<*(pp+1)<<endl;
cout<<*(pp+2)<<endl;
}
运行结果:
pp等于p意味着pp的值等于p的地址,*pp就是p地址存放的内容,p存放的东西是b的地址,**pp就是在b地址存放的内容。
讲个故事,就好比 b是小偷,只有p知道小偷的位置,pp要找自己找小偷偷的东西,pp知道p的位置,当p带上小“ * ”意味着开始从某地找某物了,*pp模式启动,找到了b的地址,*pp找到了以后,继续开启找东西模式继续带上小 “ * ”,**pp找到了自己丢失的东西。
最后,再整理一下数组指针,指针数组和二级指针与整型数组的关系
一、指针数组与二维整型数组
int main()
{
int a[2][2]= {1,2,3,4};
//char b[3][6]= {"Zhang","Jia","chen"};
int *p[4];//指针数组
*p=a[0];
p[1]=a[0]+1;
p[2]=a[1];
p[3]=a[1]+1;
cout<<*p[0]<<endl;
cout<<*p[1]<<endl;
cout<<*p[2]<<endl;
cout<<*p[3]<<endl;
}
int main()
{
int a[2][2]= {1,2,3,4};
//char b[3][6]= {"Zhang","Jia","chen"};
int (*p)[2];//数组指针
p=a;
cout<<*p[0]<<endl;
cout<<*p[0]+1<<endl;
cout<<*p[1]<<endl;
cout<<*p[1]+1<<endl;
}
输出:
数组指针,是指向数组的指针,故只需要把数组的首地址给指针即可。
三、二级指针与二维整型数组
int main()
{
int a[2][2]= {1,2,3,4};
//char b[3][6]= {"Zhang","Jia","chen"};
int *p[4];//指针数组
p[0]=a[0];//p[0]的指针等于a[0]的地址
p[1]=a[0]+1;
p[2]=a[1];
p[3]=a[1]+1;
int **pp;
pp=p;
cout<<**pp<<endl;
cout<<**(pp+1)<<endl;//pp+1是p[1]的地址
cout<<**(pp+2)<<endl;//pp+1是p[2]的地址
cout<<**(pp+3)<<endl;//pp+1是p[3]的地址
}