在 C 编程语言中,有许多不同的方法来声明将数组作为通过指针传递的参数的函数的参数。
我准备了一个例子来说明我的意思。它是一个实现std::accumulate
C++ 中的函数。它是一个将数组中所有元素相加并返回结果的函数。
我可以这样写:
int accumulate(int n, int *array)
{
int i;
int sum = 0;
for (i = 0; i < n; ++i) {
sum += array[i];
}
return sum;
}
这也可以写成this(这意味着完全相同的事情):
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
with &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[]
(and int *array
) over int (*array)[]
你可以写array[X]
代替(*array)[X]
当你想获取索引时。
但因为我不是专业人士,我会问你更喜欢哪个版本。
什么时候用什么?选择其中一种而不是另一种的原因是什么?
我大部分都用过int (*array)[N]
但我发现其他两种方法也很常见。