坚持将双指针管理的内存复制到二维数组

stuck on copying memory managed by a double pointer to a two-dimensional array

本文关键字:内存 复制 二维数组 管理 指针 坚持      更新时间:2023-10-16

代码如下:

#include <iostream>
using std::cout;
int main(int argc, char ** argv)
{
int** p;
int a[2][3]={{-1,-1,-1},
{-1,-1,-1}};
int k=1;
p = new int *[2];
for(int i=0;i<2;i++) {
p[i] = new int[3];
for(int j=0;j<3;j++) {
p[i][j] = k++;
}
}
memcpy(a,p,2 * 3 * sizeof(int));
for(int i=0;i<2;i++){
for(int j=0;j<3;j++)
cout<<a[i][j]<<" ";
cout<<endl;
}
delete [] p;
return 0;
}

运行后出现意外结果:

26573888 0 26573920
0   0   0

我认为它复制了地址而不是值,所以我将memcpy(a,p,2 * 3 * sizeof(int));行更改为

memcpy(a,p[0],2 * 3 * sizeof(int));

并打印出终端:

1 2 3
0 0 0

如何理解以上结果?谁能帮我?

p[0][2]p[1][0]猜测
地址不连续?

p[0]的类型是什么?

int*

a[0]的类型是什么?

int[3]

a[0]在适当的上下文中衰减到指针(例如,当作为参数传递给函数时(,但它本身就不是指针,与从一开始就正确的p[0]完全相反。例如,如果您比较两者的大小(sizeof(a[0])给出三个整数的大小,sizeof(p[0])给出指针的大小(,您会注意到差异。

数组成员总是一个接一个地连续放置,所以对于a,有两个数组一个接一个地放置:

a: { { -1, -1, -1 }, {-1, -1, -1 } }

对于实际上完全相同p,每个成员一个接一个地连续跟随;只是,这一次,成员是真正的指针(即内存中的某个地址(。还有其他数组,但这些(必须(放置在其他地方:

p: { <pointer>, <pointer> }
|          |
V          |
{ 1, 2, 3}   |
V
{ 4, 5, 6}

所以总而言之,你的猜测是正确的。

您必须每行执行一个memcpy才能获得预期的结果:

memcpy(a[0], p[0], 3 * sizeof(int));
memcpy(a[1], p[1], 3 * sizeof(int));

原因是行不连续。

活在神霹雳上

你在混合东西...

另一个问题(尤其是公认的答案(很好地解释了它。 您有一个静态二维数组和一个int**

这两个看起来相同,但事实并非如此。编译器知道哪个是哪个,所以一个是连续布局的,另一个不是。

您甚至可以在代码中看到这一点。 一旦你写

int a[2][3]={{-1,-1,-1},
{-1,-1,-1}};

其中对象是用a表示的内存块

但后来你写

p = new int *[2];
for(int i=0;i<2;i++) {
p[i] = new int[3];
for(int j=0;j<3;j++) {
p[i][j] = k++;
}
}

其中有一个对象p.然后用行p[i] = new int[3]继续制作 2 个单独的int[3]对象。 这些谎言谁知道在哪里。并且它们的地址被分配给指针p[i].

TL;博士:int[2][3]类型与int**有根本的不同,它们不是微不足道的互操作。