问题
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_LENGTHto 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