指针和数组
编译器在编译的时候会将数组名转化为对应类型的指针
数组注意点
不能直接用一个数组初始化另一个数组,也不能用一个数组给另一个数组赋值
void arrayassigntest()
{
int a[10]={0};
int b[10]=a;
}
此时提示数组可以用大括号的方式初始化,第四行用指针初始化数组,所以报错
void arrayassigntest()
{
int a[10]={0};
int b[10]={0};
a=b;
}
如果用一个数组给另一个数组初始化,会提示数组赋值无效
上述两种情况的原因都是在于使用数组名的时候,会将数组名转为指针
使用指针遍历数组
void traversearraybyp()
{
int a[7]={1,2,3,4,5,6,7};
int *s=a;
int *e=&a[7];
for (int *p=s;p!=e;++p) {
cout<<*p<<endl;
}
/*for (int i=0;i<sizeof(a)/sizeof(a[0]);++i) {
cout<<a[i]<<endl;
}*/
}
int *e=&a[7]指向了尾后元素之后的地址,类似于尾后迭代器
当指针指向数组的某个元素时,用指针和下标访问数组时,下标可以为负数
void negativeindex()
{
int a[7]={1,2,3,4,5,6,7};
int *p=&a[4];
cout<<p[-2]<<endl;
}
复杂数组声明的理解
数组本身是对象,所以存在数组的指针和数组的引用,而指针也是对象,所以存在指针的数组,但是引用不是对象,所以不在引用的数组
int *p[10]={nullptr};//指针的数组,每个数组的内容都是一个int指针
//int &r[10]; 错误,不存在引用的数组
因为数组的指针是对象,所以还存在数组的指针的引用和数组的指针的指针
int a[10]={0};
int *p[10]={nullptr};
int (*ap)[10]=&a;//ap指针指向一个长度为10的int数组
int (&ar)[10]=a;//ar是数组a的引用
int *(*app)[10]=&p;//app是指针数组的指针
int *(&apr)[10]=p;//apr是指针数组的引用
注意,这里int (*ap)[10]=&a不能写成int (*ap)[10]=a,因为a是int数组,编译时被解读为指针,而不是数组的指针
同理,int *(*app)[10]=&p也不能写成int *(*app)[10]=p,因为p是指针数组,编译时被解读为指针的指针
关于ap ar app的识别方法如下
int (*ap)[10],先看括号里面的ap,我们知道这是一个变量,看到前面的*,判断这是个指针,之后 看到[10],断定该指针指向一个数组,最后看到int,知道指向的数组元素类型是int
int (&ar)[10],先看括号里面的ar,我们知道这是一个变量,看到前面的&,判断这是个引用,之后 看到[10],断定该引用绑定一个数组,最后看到int,知道绑定的数组元素类型是int
int *(*app)[10],先看括号里面的app,我们知道这是一个变量,看到前面的*,判断这是个指针,之后 看到[10],断定该指针指向一个数组,最后看到int *,知道指向的数组元素类型是int指针
int *(&apr)[10],先看括号里面的apr,我们知道这是一个变量,看到前面的&,判断这是个引用,之后 看到[10],断定该引用绑定一个数组,最后看到int *,知道绑定的数组元素类型是int指针
总的来说,数组的指针和引用,以及数组指针的指针的读法是括号内,然后两边
使用数组指针二维数组
void twodimarray()
{
int a[3][4]={1,2,3,4,5};
for (int (*ap)[4]=&a[0];ap<&a[0]+3;++ap) {分别取行地址
for (int *p=ap[0];p<ap[0]+4;++p) {分别遍历每行
cout<<*p<<endl;
}
}
}
参考:
《C++ Primer》
欢迎大家评论交流,作者水平有限,如有错误,欢迎指出