例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
全文总结:最重要一点要明白: 二维数组每个元素内存中是连续存放的,而指向指针的指针变量本质上还是指针变量,即存放地址的变量而已。