如果以下是可能的:
MyFunction(int *array, int size)
{
for(int i=0 ; i<size ; i++)
{
printf(“%d”, array[i]);
}
}
main()
{
int array[6] = {0, 1, 2, 3, 4, 5};
MyFunction(array, 6);
}
为什么下面不是?
MyFunction(int **array, int row, int col)
{
for(int i=0 ; i<row ; i++)
{
for(int j=0 ; j<col ; j++)
{
printf(“%d”, array[i][j]);
}
}
}
main()
{
int array[3][3] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
MyFunction(array, 3, 3);
}
最佳答案
首先,一些standard语言:
6.3.2.1 Lvalues, arrays, and function designators
...
3 Except when it is the operand of the sizeof operator or the unary & operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.
给出声明
int myarray[3][3];
myarray
的类型是“int
的三元素数组的三元素数组”。按照上面的规则,当你写的时候
MyFunction(myarray, 3, 3);
表达式 myarray
其类型从“int
的三元素数组的三元素数组”隐式转换(“衰减”)为“指向int
的三元素数组的指针”,或int (*)[3]
.
因此,您的函数原型(prototype)需要是
int MyFunction(int (*array)[3], int row, int col)
请注意 int **array
与int (*array)[3]
不相同;指针算法会有所不同,因此您的下标不会指向正确的位置。请记住,数组索引是根据指针算法定义的:a[i]
== *(a+i)
, a[i][j] == *(*(a + i) + j)
. a+i
将根据是否 a
产生不同的值是一个 int **
或 int (*)[N]
.
此特定示例假设您始终传递一个 Nx3 元素数组 int
;如果你想处理任何 NxM 大小的数组,就不是很灵活。解决这个问题的一种方法是显式传递数组中第一个元素的地址,这样您只需传递一个简单的指针,然后手动计算正确的偏移量:
void MyFunction(int *arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", a[i*col+j]);
}
int main(void)
{
int myarray[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
...
MyFunction(&myarray[0][0], 3, 3);
由于我们将一个简单的指针传递给 int
, 我们不能在 MyFunc
中使用双下标; arr[i]
的结果是一个整数,而不是一个指针,所以我们必须在一个下标操作中计算数组中的完整偏移量。请注意,此技巧仅适用于真正的多维数组。
现在,一个 **
可以表示以二维结构组织的值,但构建方式不同。例如:
void AnotherFunc(int **arr, int row, int col)
{
int i, j;
for (i = 0; i < row; i++)
for (j = 0; j < col; j++)
printf("%d", arr[i][j]);
}
int main(void)
{
int d0[3] = {1, 2, 3};
int d1[3] = {4, 5, 6};
int d2[3] = {7, 8, 9};
int *a[3] = {d0, d1, d2};
AnotherFunc(a, 3, 3);
...
}
按照上面的规则,当表达式 d0
, d1
, 和 d2
出现在 a
的初始化程序中,它们的类型都从“int
的三元素数组”转换为“指向int
的指针”。同样,当表达式 a
出现在对 AnotherFunc
的调用中,其类型从“指向int
的指针的三元素数组”转换为“指向int
的指针的指针”。
请注意,在 AnotherFunc
中我们对两个维度都下标,而不是像在 MyFunc
中那样计算偏移量.那是因为 a
是指针 值的数组。表达式 arr[i]
从位置 arr
获取第 i 个指针值偏移量;然后我们找到从该指针值偏移的第 j 个整数值。
下表可能会有所帮助 - 它显示了各种数组表达式的类型以及它们根据声明衰减到什么(T (*)[N]
是指针类型,而不是数组类型,因此它不会衰减):
Declaration Expression Type Implicitly Converted (Decays) to ----------- ---------- ---- -------------------------------- T a[N] a T [N] T * &a T (*)[N] *a T a[i] T T a[M][N] a T [M][N] T (*)[N] &a T (*)[M][N] *a T [N] T * a[i] T [N] T * &a[i] T (*)[N] *a[i] T a[i][j] T T a[L][M][N] a T [L][M][N] T (*)[M][N] &a T (*)[L][M][N] *a T [M][N] T (*)[N] a[i] T [M][N] T (*)[N] &a[i] T (*)[M][N] *a[i] T [N] T * a[i][j] T [N] T * &a[i][j] T (*)[N] *a[i][j] T a[i][j][k] T
高维数组的模式应该很清楚。
关于关于指针和多维数组的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3911244/