int * vs int [] vs int (*)[] in function parameters. Which one should I use?

荒凉一梦 提交于 2020-01-05 09:30:59

问题


In the C-programming language there are many different ways to declare the parameter of a function that takes an array as an argument passed through a pointer.

I have prepared an example that shows you what I mean. It is an implementation of the std::accumulate function in C++. It is a function that performes addition of all elements in an array and returns the result.

I can write it like this:

int accumulate(int n, int *array)
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += array[i];
    }
    return sum;
}

This can also be written to this (which means the exact same thing):

int accumulate(int n, int array[])
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += array[i];
    }
    return sum;
}

I can also write it like this:

int accumulate(int n, int (*array)[])
{
    int i;
    int sum = 0;
    for (i = 0; i < n; ++i) {
        sum += (*array)[i];
    }
    return sum;
}

All these options are very similar and generate the same executable code but they have a slight difference which is how the caller passes the arguments.

This is how the first two versions gets called:

int main(void)
{
    int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
    printf("%d\n", accumulate(ARRAY_LENGTH(a), a));
    return 0;
}

This is how the thrid version gets called:

int main(void)
{
    int a[] = {3, 4, 2, 4, 6, 1, -40, 23, 35};
    printf("%d\n", accumulate(ARRAY_LENGTH(a), &a));
    return 0;
}

Note that the third option requires to user to explicitly specify the address of a with &a. The first two options does not require this because arrays implicitly gets converted into pointers to the same type in C.

I have always preferred the third approach.

This is why:

  • It is more consistent with how other types are passed by pointers.

    int draw_point(struct point *p);
    
    int main()
    {
        struct point p = {3, 4};
        draw_point(&p); // Here is the 'address of' operator required.
    }
    
  • It makes it possible to use macros like ARRAY_LENGTH to get the amount of elements in the array.

    #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));
    }
    

The only advantage I see with int array[] (and int *array) over int (*array)[] is that you get to write array[X] instead of (*array)[X] when you wish to grab an index.

But because I am not a professional I will ask you which version you prefer.

When do you use what? What are the reasons to choose one of these options over another?

I have mostly used int (*array)[N] but I see that the other two approaches are quite common as well.


回答1:


When used as function parameters, int array[] and int *array are same. You can use either. It is matter of taste. int (*array)[] is tedious and not used widely.

int (*array)[n] is used most widely when 2D array is passed to a function. In that case you can access the element of array as array[i][j].




回答2:


I also prefer the third variant, but it is not very commonly used. If so, with C99 I would write:

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

such that sizeof *array works in all cases inside the function.



来源:https://stackoverflow.com/questions/27890375/int-vs-int-vs-int-in-function-parameters-which-one-should-i-use

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!