函数参数中的int * vs int [] vs int(*)[]。我应该使用哪一个?

时间:2015-01-11 18:09:08

标签: c arrays function pointers parameters

在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;
}

这就是调用thrid版本的方式:

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]抓住一个指数。

但是因为我不是专业人士,我会问你喜欢哪个版本。

你什么时候用?选择其中一种选择的原因是什么?

我主要使用{{1}},但我发现其他两种方法也很常见。

2 个答案:

答案 0 :(得分:3)

当用作函数参数时,int array[]int *array是相同的。你可以使用其中之一。这是品味的问题。 int (*array)[]繁琐且不广泛使用。

当2D数组传递给函数时,

int (*array)[n]被最广泛地使用。在这种情况下,您可以访问数组元素array[i][j]

答案 1 :(得分:1)

我也更喜欢第三种变体,但它并不常用。如果是这样,用C99我会写:

int accumulate(size_t n, int (*array)[n]) { ....

这样sizeof *array适用于函数内的所有情况。