# int * vs int [N] vs int (*)[N] in functions parameters. Which one do you think is better?

When programming in C (or C++) there are three different ways to specify the parameter in a function that takes an array.

Here is an example (implementing `std::accumulate` from C++ in C) that shows you what I mean.

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 very 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 options 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 option 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))

void this_works(int (*array))
{
/* This works! */
printf("%d\n", ARRAY_LENGTH(*array));
}

void this_is_invalid_and_dangerous(int array)
{
/* 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`) is that you get to write `array[X]` instead of `(*array)[X]` when you wish to grab an index.

What are your professional thoughts on this? Which approach do you think is better and why? Do you ever mix the two? If so when do you choose what?

Like I said have I always preferred using `int (*array)[N]` but I see that the other two approaches are quite common as well.

• “Both versions are very similar and generate the same executable code” – it seems that one version receives an `*int` while the other gets an `**int`, so I doubt they'll compile to the same instructions. Furthermore, some of your examples use pointers, others arrays without explicit lengths as in `(*array)[]`, and others provide a static length: `(*array)`, and I'd think all of those are different. To answer what manner of passing arrays is safe and sensible, you should also state what C standard you are following, and whether you're allowing compiler-specific extensions. – amon Jan 10 '15 at 14:29
• Try compiling `size_t function(int (*a)[]){return sizeof(*a);}`. To me it fails to compile using `gcc -std=c99` and prints this error message: `main.c: In function ‘function’: main.c:6:18: error: invalid application of ‘sizeof’ to incomplete type ‘int[]’` This suggests that `*a` has the type `int[]` and not `int *`. – wefwefa3 Jan 10 '15 at 15:44
• I do not have access to the standard documents myself but I assume that `gcc -std=c99 -pedantic` follows the C99 standard in each and every point. – wefwefa3 Jan 10 '15 at 15:55
• I do not think that I am "good enough" to make these assumptions so I made a question on stackoverflow here: <stackoverflow.com/questions/27878583/…>. Hopefully some smart guy with a copy of the standard documents can answer the question. – wefwefa3 Jan 10 '15 at 16:51

## 4 Answers

In practice, you'll see

``````int accumulate( int n, int *array)
``````

most often. It's the most flexible (it can handle arrays of different sizes) and most closely reflects what's happening under the hood.

You won't see

``````int accumulate( int (*array)[N] )
``````

as often, since it assumes a specific array size (the size must be specified).

If your compiler supports variable-length array syntax, you could do

``````int accumulate( size_t n, int (*array)[n] )
``````

but I don't know how common that is.

• It seems like `int (*)[]` (with unspecified size) is legal in C but illegal in C++. It compiles without problems `gcc -std=c89 -pedantic` but fails to compile using `g++`. – wefwefa3 Jan 12 '15 at 7:46
• I made a question on Stackoverflow where I asked about it (`int (*p)[])` here: <stackoverflow.com/questions/27897646/…> hopefully it will get some clarifying answers. – wefwefa3 Jan 12 '15 at 8:18
• @elias: `int (*a)[]` is an incomplete type; it's legal as long as you don't try to do anything that requires the size of the type to be known. For example, you couldn't use `sizeof *a` to get the size of the array in that case. Also, remember that a pointer to an N-element array is a different type from a pointer to an M-element array; they won't be interchangeable. As a matter of safety, you always want to specify the size of the array parameter. – John Bode Jan 12 '15 at 12:21
• `int arr={0};int (*p) = &arr `Why `*p` is the address of the array?I know `*p` is `int ` type, but p stores the address of array. Since dereference p, I thought it will be 0, the value of `arr`. Coz that's what stores in the address indicated by p. – MMMMMCCLXXVII Nov 21 '17 at 15:28
• @MMMMMCCLXXVII: `*p` is not the address of the array - it's the array object itself (`p == &arr`, so `*p == arr`). Anywhere you'd write `arr`, write `(*p)` instead - `*arr == *(*p)`, `arr[i] == (*p)[i]`, etc. – John Bode Nov 21 '17 at 15:39

In C, when the array notation is used for a function parameter, it is automatically transformed into a pointer declaration, so declaring parameter as int* array and int array[] are equivalent. I tend to use second one because it is more clear that function expects an array as an argument.

Declaring function parameter as int (*array)[] is not equivalent to previous two, it is transformed to int** and it should be used when value of the parameter itself could be changed in function, i.e. reallocation of the array.

• `int function(int (*a)[]){printf("%d\n", sizeof(*a));}` fails to compile and prints this error message (using `gcc -std=c99)`: `main.c:6:26: error: invalid application of ‘sizeof’ to incomplete type ‘int[]’` which shows that `*a` has the type `int[]` and not `int *`. – wefwefa3 Jan 10 '15 at 15:38
• @elias Yes, `int (*array)` means that array is a pointer to an array of 10 integers, which is semantically the same as `int**`, the only difference is that it gives possibly false and dangerous idea of the array size. Try passing array of different size and see if it still prints the correct value. Btw, note that there is no [] in C after compile time, it all eventually decays to pointers. – vasicbre Jan 10 '15 at 16:12
• I have become very confused about. I feel that this is something that the people and stackoverflow should answer so I made a question there: <stackoverflow.com/questions/27878583/…> – wefwefa3 Jan 10 '15 at 16:48
• Good idea, I see a lot of clarifying answers for me as well. Thanks. – vasicbre Jan 10 '15 at 17:12

You say that there are 3 ways in C and C++, but C++ actually makes a fourth available:

``````template<std::size_t n>
void arrayFunction(std::array<int,n> &array)
{ ...}
``````

This has several advantages over the solutions you suggest:

• The parameter for the size of the array will be automatically determined on use by the compiler, meaning you don't have to specify it
• The size is a compile time constant, meaning that the compiler can perform many optimizations that are impossible for the versions you suggest
• It is impossible to specify an incorrect size, as the size is part of the type of the array

The first declaration also allows you write the function differently:

``````int accumulate(int n, int *array)
{
int sum = 0;
while (n-- > 0) sum += *array++;
return sum;
}
``````

so you don't need the variable i.

Whatever's idiomatic to the code base should be preferred, followed by whatever's the easiest to understand, followed at some distance by whatever's the most performant. The second declaration is the easiest to understand.