【发布时间】:2015-01-11 18:09:07
【问题描述】:
在 C 编程语言中,有许多不同的方法来声明函数的参数,该函数将数组作为通过指针传递的参数。
我准备了一个例子来说明我的意思。它是 C++ 中 std::accumulate 函数的实现。它是一个执行数组中所有元素相加并返回结果的函数。
我可以这样写:
int accumulate(int n, int *array)
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
这也可以写成这个(意思完全一样):
int accumulate(int n, int array[])
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
我也可以这样写:
int accumulate(int n, int (*array)[])
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += (*array)[i];
}
return sum;
}
所有这些选项都非常相似,并生成相同的可执行代码,但它们在调用者传递参数的方式上略有不同。
前两个版本的调用方式如下:
int main(void)
{
int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
printf("%d\n", accumulate(ARRAY_LENGTH(a), a));
return 0;
}
这是第三版的调用方式:
int main(void)
{
int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
return 0;
}
请注意,第三个选项要求用户使用&a 明确指定a 的地址。前两个选项不需要这样做,因为数组在 C 中隐式转换为指向相同类型的指针。
我一直更喜欢第三种方法。
这就是为什么:
-
更符合其他类型的指针传递方式。
int draw_point(struct point *p); int main() { struct point p = {3, 4}; draw_point(&p); // Here is the 'address of' operator required. } -
它可以使用像
ARRAY_LENGTH这样的宏来获取数组中元素的数量。#include <stdio.h> #define ARRAY_LENGTH(A) (sizeof(A) / sizeof(A[0])) void this_works(int (*array)[10]) { /* This works! */ printf("%d\n", ARRAY_LENGTH(*array)); } void this_is_invalid_and_dangerous(int array[10]) { /* This does NOT work because `array` is actually a pointer. */ printf("%d\n", ARRAY_LENGTH(array)); }
我看到int array[](和int *array)相对于int (*array)[] 的唯一优势是,当您希望获取索引时,可以使用array[X] 而不是(*array)[X]。
但因为我不是专业人士,所以我会问你更喜欢哪个版本。
你什么时候用什么?选择其中一个选项而不是另一个选项的原因是什么?
我主要使用int (*array)[N],但我发现其他两种方法也很常见。
【问题讨论】:
-
为什么这被否决了?
-
我对这两个答案都不满意。他们都没有提到
pointer to array——这是int array[](在函数参数列表的上下文中实际上是int *)和int (*array)[]之间的定义区别。 -
@Jonathan 如果您(或其他人)有什么要补充的,您可以提出一个新的答案,如果它更好,我会接受。也许我这次很早就接受了一个答案,这会阻止新的答案出现。当我回顾这个问题时,我也意识到这个问答网站可能过于“基于意见”,但如果您认为其他答案遗漏了什么,请继续提出新的答案。
标签: c arrays function pointers parameters