【发布时间】:2010-03-26 01:01:37
【问题描述】:
我有一个函数,有时用常规数组调用,有时用动态数组调用。
如果我将函数定义为
function_name(int[10][10] a)
并发送 int** 作为参数,我收到警告。相反,如果我声明
function_name(int** a)
并发送 int[][] 作为参数(转换后)我无法访问函数内的数组元素。
什么是最正确的方法?
【问题讨论】:
我有一个函数,有时用常规数组调用,有时用动态数组调用。
如果我将函数定义为
function_name(int[10][10] a)
并发送 int** 作为参数,我收到警告。相反,如果我声明
function_name(int** a)
并发送 int[][] 作为参数(转换后)我无法访问函数内的数组元素。
什么是最正确的方法?
【问题讨论】:
当一个数组被传递给一个函数时,它“衰减”为指向其第一个元素的指针。所以,给定:
T a[10];
f(a);
在f(a)调用中,a实际上是&a[0],即指针,类型为T *(&a[0]的类型)。
当你有一个数组时,同样的规则适用:
T a[10][5];
f(a);
a 再次衰减为指针,等于&a[0]。 a[0] 的类型为“T 的数组 [5]”。所以,&a[0] 的类型是“指向T 的数组 [5] 的指针”,也就是说,如果你要声明一个指针 p 以设置为等于 &a[0],你会这样做:
T (*p)[5]; /* parentheses because [] binds tighter than * */
p = &a[0];
鉴于上述情况,假设您的数组在调用代码中声明为int a[10][10];,您应该将您的函数声明为:
function_name(int (*a)[10]);
欲了解更多信息,请参阅this。
function_name(int[10][10] a) 中存在语法错误——您需要在“变量”名称后指定数组大小:function_name(int a[10][10])。其实上面等价于function_name(int (*a)[10]),因为上面提到了“腐烂”。
编辑:啊,我想我现在明白了。由于上述原因,您不能声明一个同时采用“二维”数组和指向指针的函数(指针的“衰减”只发生一次)。指向指针的指针可能不指向连续数据,并且每个“行”中可能有不同数量的元素。数组数组不能具有这些属性。它们是根本不同的。
【讨论】:
int ** 和 int [][] 不一样。
前者是pointer to pointer to int,而第二个是int 的二维数组。
int[][] decays to int (*)[] when you pass it as argument to function.
void func(int arr[][10]) { //decays to `int (*arr)[10]`
printf("%d correct", arr[1][9]); //10th element of 2nd row
//printf("%d correct", (*(arr + 1))[9]); //same as above
}
int main() {
int (*arr)[10]; //pointer to array of ints
arr = malloc(sizeof(int (*)[]) * 2); //2 rows & malloc will do implicit cast.
arr[1][9] = 19;
func(arr);
return 0;
}
【讨论】: