更新:已报告此问题的可能重复。虽然提交给that question的答案部分解决了这个问题,但要解释why we can't use double pointers to represent two dimensional arrays,不指定如何访问存储在指针中的值的正确内存地址;这是这个问题的主题。这个问题中的明确答案可以很好地澄清给那些在未来 中困惑的人,关于为什么这是一个被误解的概念以及如何解决它的替代方法。这对于希望跟踪输出以更好地理解概念的未来读者可能是有用的(如果仔细观察comments by the OP in that question,您会发现跟踪不够清楚,无法让他理解。这个问题的 部分 提供了一个更好的跟踪示例,以便几乎任何人都可以轻松理解)
(问题的其余部分在于其未经编辑的荣耀,以便未来的读者能够反思类似的错误,如果它们碰巧成功的话。)
我尝试了什么:
以下是示例代码:
int main()
{
int a[2][2]={{5,7},
{0,1}};
int** ptr=(int**)a;
int i,j;
for(i=0;i<2;i++){
for(j=0;j<2;j++){
printf("%d printing from==>%x\n",&ptr[i][j],((&ptr[i])+j));
}
}
getch();
return(0);
}
在上面的代码中,我试图在指针ptr的帮助下打印矩阵a [] []中存在的值。在这样做时,我正在跟踪实际发生打印的地址(在内存地址中)。我似乎遇到了以下形式的灾难性输出:
从==&gt; 12ff7c打印5 9从==&gt; 12ff80打印 7从==&gt; 12ff80打印 11从==&gt; 12ff84打印
然后我修改了一行:
printf("%d printing from==>%x\n",&ptr[i][j],((&ptr[i])+j));
用这个:
printf("%d printing from==>%d\n",&ptr[i][j],*((&ptr[i])+j));
知道这些地址中存在 实际 的值:
从==&gt; 5打印5 9从==&gt; 7打印 7从==&gt; 7打印 11从==&gt; 0打印
我对此的看法是:&amp; ptr [i] [j]相当于(*(&amp; ptr [i])+ j)) 和((&amp; ptr [i])+ j))并没有真正告诉我那些数字的地址,因为&amp; ptr [i]定义了一个地址,在这种情况下增加了j(但是因为j在每个外部循环迭代中重置为0;这将导致相同的内存地址被指向两次) 我对这一思路错了吗?
答案 0 :(得分:5)
2D数组和指针指针是不同的动物!
一个二维数组,比如int arr[N][M]
,是一个N * M个连续元素的数组,具有以下关系&arr[i][j] == &arr[0][0] + i * M + j
。
指针指针是指向指针数组的指针,每个指针都指向另一个数组。
那你能做什么?
将数组处理为具有显式索引的一维数组
int main()
{
int a[2][2]={{5,7},
{0,1}};
int* ptr=a[0]; // a[0] decays to a pointer...
int i,j;
for(i=0;i<2;i++){
for(j=0;j<2;j++){
printf("%d printing from==>%x\n",ptr[j + 2 *i],ptr + j + 2 * i);
}
}
//getch();
return(0);
}
明确地创建一个指针数组
int main()
{
int a[2][2]={{5,7},
{0,1}};
int *b[] = { a[0], a[1] }; // array of pointers pointing to beginning or rows
int** ptr=b; // b decays to a pointer to pointer
int i,j;
for(i=0;i<2;i++){
for(j=0;j<2;j++){
printf("%d printing from==>%x\n",ptr[i][j],&(ptr[i][j]));
}
}
//getch();
return(0);
}
明确地使用指向确定大小的数组的指针:
int main()
{
int a[2][2]={{5,7},
{0,1}};
int (*ptr)[2] = a; // a decays to a pointer arrays of size 2
int i,j;
for(i=0;i<2;i++){
for(j=0;j<2;j++){
printf("%d printing from==>%x\n",ptr[i][j],&(ptr[i][j]));
}
}
//getch();
return(0);
}
另请注意,我在上面的代码中没有明确的强制转换,让编译器控制了无效级别。