例1:
#include <iostream>
using namespace std;
int main()
{
int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };
int *ptr = (int *)array;
int i = 0;
while (i < 6)
{
cout << " " << ptr[i];
i++;
}
return 0;
}
输出:
分析:可看出array[0][2]和array[1][0]地址是连续的。
例2:
#include <iostream>
using namespace std;
int main()
{
int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 }};
int **ptr = (int **)malloc(2 * sizeof(int));
if (ptr == NULL)
{
cout << "malloc error!" << endl;
exit(1);
}
for (int i = 0; i < 2; i++)
{
ptr[i] = (int *)malloc(3 * sizeof(int));
if (ptr[i] == NULL)
{
cout << "malloc error!" << endl;
exit(1);
}
for (int j = 0; j < 3; j++)
{
ptr[i][j] = array[i][j]; // 因为在堆上分配了内存空间
}
}
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << " " << ptr[i][j];
}
cout << endl;
free(ptr[i]);
}
free(ptr);
return 0;
}
输出:
分析:
malloc分配的内存空间如上图所示。可看出ptr[0][2]和ptr[1][0]地址不一定是连续的。
例3:
#include <iostream>
using namespace std;
int main()
{
int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 }};
int **ptr = (int**)array; /* array相当于指向一维数组的指针变量;int (*ptr)[3] = array;下面cout << " " << ptr[i][j]; 就不会报错了。*/
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
//cout << " " << ptr[i][j]; /* 报错! 原因见下面分析 */
cout << " " << *((int*)ptr + 3*i + j);
}
cout << endl;
}
return 0;
}
输出:
分析:重点分析下//cout << " " << ptr[i][j]这行代码。
执行 int **ptr = (int**)array;
ptr的内存布局如下:
array的内存布局如下:
执行 int **ptr = (int**)array; 之后,ptr的值(起始地址)就为array的值,因为32位系统存放地址都是4字节,int也是4字节,所以*(ptr+0)就是取内存里面的数据,刚好值就为array[0][0]。因为ptr是指向指针的指针,所以*(ptr+0)为ptr[0][0]的地址,即&ptr[0][0]值为array[0][0],&ptr[0][1]为array[0][0]+sizeof(int), &ptr[0][2]为array[0][0]+2*sizeof(int) ; *(ptr+1)为ptr[1][0]的地址,即&ptr[1][0]值为array[0][1],&ptr[1][1]为array[1][0]+sizeof(int),&ptr[1][2]为array[1][0]+2*sizeof(int) ;
为什么 //cout << " " << ptr[i][j];报错呢?以ptr[0][0]为例,&ptr[0][0]值为array[0][0],这里array[0][0]=1;而地址为1的内存里面的数据是不能访问的,所以报错。
补充知识:
如:
#include <iostream>
using namespace std;
int main()
{
short int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };
short int **ptr = (short int **)array;
cout << "&array = " << hex << &array << endl;
cout << "ptr = " << hex << ptr << endl;
cout << "ptr[0] = " << hex << ptr[0] << endl;
cout << "ptr[1] = " << hex << ptr[1] << endl;
cout << "&ptr[0][0] = " << hex << &ptr[0][0] << endl;
cout << "&ptr[0][1] = " << hex << &ptr[0][1] << endl;
cout << "&ptr[0][2] = " << hex << &ptr[0][2] << endl;
cout << "&ptr[1][0] = " << hex << &ptr[1][0] << endl;
cout << "&ptr[1][1] = " << hex << &ptr[1][1] << endl;
cout << "&ptr[1][2] = " << hex << &ptr[1][2] << endl;
return 0;
}
输出:
分析:
short int 是2个字节,而存放地址是4个字节。即array[0][0]占2个字节,ptr[0]也就是*ptr占4个字节。
因为X86平台是小端序(数据低位存放在低内存地址),所以二维数组内存array内存从低到高前8个字节为:
注:关于大小端网上资料很多,这里不做讲解。
ptr[0]取前4个字节,因为是小端序,所以ptr[0]=&ptr[0][0] =0x00020001,
同理ptr[1]=&ptr[1][0] = 0x00040003;(这里"="理解为等于号)
例4:
#include <iostream>
using namespace std;
int main()
{
int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };
int (*ptr)[3] = array;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 3; j++)
{
cout << " " << ptr[i][j]; /* 因为ptr是指向一维数组的指针变量,所以完全等价: cout << " " << array[i][j]; */
cout << " " << *((int*)ptr + 3 * i + j); // 相当于:cout << " " << *((int*)array + 3 * i + j);
}
cout << endl;
}
return 0;
}
输出:
例5:
#include <iostream>
using namespace std;
int main()
{
int array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };
int **ptr = (int **)array;
cout << "array = " << hex << array << endl;
cout << "array[0] = " << hex << array[0] << endl;
cout << "ptr = " << hex << ptr << endl;
cout << "array[0][0] = " << hex << array[0][0] << endl;
for (int i = 0; i < 2; i++)
{
*(ptr + i) = array[i]; //???
cout << "array[0][0] = " << hex << array[0][0] << endl;
cout << "array[0][1] = " << hex << array[0][1] << endl;
}
return 0;
}
输出:
分析:
注意:array[0]和ptr[0]意义完全不同。
array[0]是0行0列地址,即和array的值一样。ptr[0]即*ptr,为地址为ptr值的内存里面存的数据。这程序里刚好为array[0][0]的值,执行*(ptr + i) = array[i];之后,就把ptr值的内存里面存的数据修改为array[i]的值,即array[0][0]也修改为了array[i]的值。
补充一下:
如:
#include <iostream>
using namespace std;
int main()
{
short array[2][3] = { { 1, 2, 3 },{ 4, 5, 6 } };
short **ptr = (short int **)array;
cout << "array = " << hex << array << endl;
cout << "array[0] = " << hex << array[0] << endl;
cout << "ptr = " << hex << ptr << endl;
cout << "array[0][0] = " << hex << array[0][0] << endl;
for (int i = 0; i < 2; i++)
{
*(ptr + i) = array[i]; //???
cout << "array[0][0] = " << hex << array[0][0] << endl;
cout << "array[0][1] = " << hex << array[0][1] << endl;
cout << "array[0][2] = " << hex << array[0][2] << endl;
cout << "array[1][0] = " << hex << array[1][0] << endl;
}
return 0;
}
输出:
分析:
有了上面的分析这就很好理解了。(注意X86平台是小端)
如果是大端平台,执行 *(ptr + i) = array[i];之后array[0][0]=0x004E,array[0][1]=0xfdbc
全文总结:最重要一点要明白: 二维数组每个元素内存中是连续存放的,而指向指针的指针变量本质上还是指针变量,即存放地址的变量而已。