in the man page for the pipe
system call, I see
/* On all other architectures */
int pipe(int pipefd[2]);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Obtain O_* constant definitions */
#include <unistd.h>
int pipe2(int pipefd[2], int flags);
the functions accept an array with a fixed size as their arguments int pipe(int pipefd[2])
but I know that in C you cannot pass an array as an argument because it decays to a pointer to the first element of the array. This question is mostly aimed at getting coding advice: I always use this signature: func(int *array, int len)
whenever passing an array comes up in my programming, so I was wondering when would something like this be useful? The only use case I can think of is letting the user of the API know that you must pass an array sized for 2 elements (in this case), but from a quick compilation test, I can see that gcc
does not complain when a mismatch occurs:
void func(int array[10])
{
}
int main(void)
{
int array[4]; // passing int[4] but expected int[10]
func(array);
return 0;
}
gcc
compiles the above code without errors or warnings. Any insight is welcome.
void func (int *array, int len)
is pretty idiomatic C so using that style is never wrong. Mind "const correctness" however, in case the function doesn't modify the contents.
You can use a fixed size array parameter if it makes sense to only ever accept such arrays. It is self-documenting code but as you noticed, it doesn't actually improve type safety since the array is adjusted to a pointer to the first element no matter. (Which is in fact why we can even write int param[]
with an incomplete array size.)
You could improve type safety by requiring a pointer to the array instead:
void func(int (*array)[10])
{
}
int main(void)
{
int array[4];
func(&array); // compiler error
return 0;
}
But using array pointers as part of the function API is odd and unusual - it might make the code harder to read. And this makes "const correctness" impossible as well.
The best combination of readability and type safety might be to use a pointer to variable-sized array instead:
#include <stddef.h>
void func (size_t size, int array[size])
{
}
int main(void)
{
int array[3];
func(4, array); // warning from gcc here
return 0;
}
This pushes the responsibility of keeping track of the array size onto the caller and some compilers may produce warnings in case it has a chance to spot mismatch at compile-time.