今天由于需要动态申请二维数组,发现以前对指针数组与数组指针的定义方式有错误,今天终于纠正并进行了一些探究。
数组指针
首先,数组指针有两类:
- 申请数组时,数组名即是一个数组指针,其地址就为数组首地址。如
int A[100]
,A,&A都是数组首地址,*A为第0个元素的值。 - 特意申请空间作为一个数组的指针,如
int (*b)[4]
,申请了一个长度为4的数组指针,这个指针有其存储空间,如下图中的0x0133FA30
,令b = &A
,则b的值为数组A的首地址。
指针数组
这个概念反倒好理解,所谓指针数组就是这个数组里面的元素都是指针,可能是int型指针,也可能是double型指针。而在一个机器中,指针的长度与指向的数据类型无关,都是一个固定值,如4Bytes.
指针数组的定义方式是:
int *a[4];
其与上面int (*b)[4]
有区别的原因是[]的优先级高于*的优先级。此处a先与[]结合成为一个长度为4的数组,然后由于*的修饰使其成为一个指针数组。而int (*b)[4]
中b先与*结合,成为一个指针,然后[4]的修饰使其成为指向长度为4的数组的指针。
程序验证
int main(){
int c[4] = { 1, 2, 3, 4 }; //申请长度为4的int数组
int *a[4]; //申请长度为4的指针数组
int (*b)[4]; //声明一个数组指针
int AA[5] = { 5, 6, 7, 8, 9 };
b = &c; //令 b 指向数组 c
for (int i = 0; i < 4; i++){
a[i] = &c[i]; //为指针数组赋值
}
cout << *a[1] << endl;
cout << *(b[0]+2) << endl; //b[0]即为数组指针b的数值(即指向的地址),加2之后指向了数组c的第二个元素
cout << c[2] << endl;
cout << "The address of c : " << c << endl;
cout << "The address of a : " << a << endl;
cout << "The address of b : " << &b << endl; //输出数组指针所在地址
cout << "The address of AA : " << AA << endl;
for (int j = 0; j < 5; j++) //出于好奇,我们来看看b[1..4]是什么内容
cout << "The content follow b : " << b[j] <<" | " << (b[j]+1) << endl;
return 0;
}
执行结果为:
可以看到,*(b[0]+2]
的值与c[2]
的值一致。
然后我们可以发现,b[1]与b[0]相差0x10,b[2]与b[1]相差0x10,也就是下标加1,指向的地址就加16(也就是声明时指定的数组长度)。这种用法虽然错误,但是让我们更加清楚理解了数组指针的定义,而且似乎可以使用这种方法来实现动态二维数组的申请:
先申请一个row*column长度的一维数组,然后再获取row个长度为column的数组指针。