目录
数组指针
如何记忆:这是一个指针,数组是指针的修饰词,指针为主,数组为辅。所以指针表达为(*ptr),数组表达式为:int []
结合在一起就是int (*ptr) [n]
数组指针表示指向一个整型的一维数组,这个一维数组的长度是n。
第一个例子:
看下图结果:ptr和ptr+1之间字节为2*16-C = 20,20正好是n*sizeof(int);说明执行p+1时,p要跨过n个整型数据的长度。
以此表明数组指针又称为行指针
#include<iostream>
using namespace std;
int main(){
int a[5] = {1,2,3,4,5};
int (*ptr)[5] =&a;
cout<<"ptr:"<<ptr<<" "<<"a:"<<a<<endl;
cout<<"ptr+1:"<<ptr+1<<" "<<"a+1:"<<a+1<<endl;
system("pause");
return 0;
}
结果如下:
a和&a指向的是同一块地址,但他们+1后的效果不同,a+1是一个元素的内存大小(增加4),而&a+1增加的是整个数组的内存大小(n*sizeof(int))。既a和&a的指向和&a[0]是相同的,但性质不同!
总结:
其实a和 &a结果都是数组的首地址,但他们的类型是不一样。
a表示&a[0],也即对数组首元素取地址,但类型为:int*,a+1表示首地址+sizeof(元素类型)。
a虽然值为数组首元素地址,但类型为:int(*)[n],所以&a+1大小为:首地址+sizeof(a)
第二个例子:
int a[3][4];
int (*ptr)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
ptr = a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
ptr++; //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
#include<iostream>
using namespace std;
int main(){
int a[3][4];
int (*ptr)[4] = a;
cout<<"ptr:"<<ptr<<" "<<"a:"<<a<<endl;
cout<<"ptr+1:"<<ptr+1<<" "<<"a+1:"<<a+1<<endl;
system("pause");
return 0;
}
ptr和ptr+1之间字节为0xFF00-0xFEF0 = 0x10 表示16个字节,正好是4*sizeof(int);正好跨过了一行,在此表明数组指针又称为行指针
指针数组
如何记忆:这是一个数组,指针是数组的修饰词,数组为为主,指针为辅。所以数组表达为int [n],指针表达式为:*p
结合之后就是int *p[n]。它有n个指针类型的数组元素
也可以这么看,整型数组里面存放的全是整形,所以指针数组里面存放的全是指针
int a;p[0] = &a,因为p[0]和p[1]都是指针。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针
for(i=0;i<3;i++)
p[i]=a[i]
这个地方的学习,怎么对照整型数组对照来学习
#include<iostream>
using namespace std;
int main(){
int *p[5];
cout<<"p:"<<p<<" "<<"&p[0]:"<<&p[0]<<endl;
cout<<"*p:"<<*p<<" "<<"p[0]:"<<p[0]<<endl;
int a[5];
cout<<"a:"<<a<<" "<<"&a[0]:"<<&a[0]<<endl;
cout<<"*a:"<<*a<<" "<<"a[0]:"<<a[0]<<endl;
cout<<"*(a+1):"<<*(a+1)<<" "<<"a[1]:"<<a[1]<<endl;
system("pause");
return 0;
}
当int a[5]={1,2,3,4,5};时的结果
解释:
1、p表示int * []数组的首地址,同时a表示int [] 数组的首地址;
2、p[0]表示该数组的第一是元素的值,由于p[0]里面的值应该是一个地址,但是我们没有赋值,所以他是一个随机地址
同时a[0]表示该数组的第一是元素的值,由于刚刚开始并没有给a[0]赋值,所以a[0]里面是一个随机数,当我们赋值之后,a[0]=1
3、&p[0]表示该数组中第一个元素的地址,也是首地址。同时&a[0]也是第一个元素的地址
上述都已经描述的很清楚了,相信大家也理解了。