#include<stdio.h>
void foo(int **arr) {
arr[1][1]++;
}
main() {
int arr[20][20];
printf("%d\n",arr[1][1]);
foo((int**)arr);
printf("%d\n",arr[1][1]);
}
答案 0 :(得分:10)
假设您声明: int arr [10] [20];
什么类型的arr?
您可能认为它是int **
,但这是不正确的。当它衰变时它实际上是
int (*)[20]
类型(比如当你将它传递给函数时);
数组衰减仅适用一次。
现在考虑以下内容,
#include<stdio.h>
#include<stdlib.h>
void foo(int arr[][20]) {
arr[1][1]++;
}
main() {
int (*arr)[20];
arr = malloc(sizeof(int (*)[]) * 2); //2 rows & malloc will do implicit cast.
printf("%d\n",arr[1][1]);
foo(arr);
printf("%d\n",arr[1][1]);
}
输出:
$ gcc fdsf.c&amp;&amp; ./a.out
0
1
arr 和 arr + 1 指向20个整数的数组。
arr + 0 - &gt; int int int ... int(20 int,con)) [0] [0] [0] [1]
arr + 1 - &gt; int int int ... int(20 int,con)) [1] [0] [1] [1]
答案 1 :(得分:7)
以下是int[2][2]
在内存中的样子:
int[2] int[2]
也就是说,一个数组紧跟另一个数组。
以下是int[2]
在内存中的样子:
int int
也就是说,一个int后面跟着另一个int。
所以,这也是int[2][2]
在内存中的样子:
int int int int
^ ^
| |___ this is arr[1][1]
|
|____ this is p[1], assuming sizeof(int*) == sizeof(int)
如果您将arr
投射到int**
,我将调用结果p
。然后它指向相同的记忆。当您执行p[1][1]
时,您无法获得arr[1][1]
。该程序的作用是,它读取p[1]
处的值,通过int的大小调整该值,并且取消引用它。如果第二个int包含,例如值“21”,那么您刚刚尝试取消引用指针“25”(如果int
是4个字节)。那不对。
数组与指针不同,2-D数组肯定与指针指针不同。
答案 2 :(得分:6)
因为foo期望指向int的指针,并且你正在向它传递一个指向20 int数组的指针。投射它不会改变它不是正确类型的事实。
答案 3 :(得分:5)
如果你这样改变,你会得到预期的结果:
#include<stdio.h>
void foo(int arr[][20]) {
arr[1][1]++;
}
int
main() {
int arr[20][20];
arr[1][1] = 1;
printf("%d\n",arr[1][1]);
foo(arr);
printf("%d\n",arr[1][1]);
}
答案 4 :(得分:4)
foo
需要知道数组大小(好吧,至少第二个数组维,首先不需要),否则它不能为[1][1]
做必要的指针算法。 / p>
答案 5 :(得分:1)
问题是2d数组的int arr[20][20]
意味着该数组存储为1d数组,并且行依次存储。当您对int **arr
建立索引时,实际上从数组的第一行获取第二个元素,然后取消引用它并在那里取第一个元素。