You can split understanding this in two parts, 1) the return value and 2) the parameter type:
int ( &fillarr() )[5] {
static int arr[5];
return arr;
}
We can have a look at the type: int (&fillarr())[5]
. To understand this, unfortunately the old C rule: "Declaration is like usage in expressions" doesn't work with references, so let's have a look at a similar declaration instead:
int (*fillarr())[5];
This is a function that returns a pointer instead of a reference to an array of size 5. How do I figure? Well, assume we do have a function f
that returns a pointer to an array of ints, how would we access the fifth element? Let's see, we first have to call the function: f()
. Then we have to dereference the result *f()
and then access the fifth element (which doesn't exist, but ignore that) (*f())[5]
which is an int
. This is exactly the declaration syntax:
int x;
int (*f())[5];
x = (*f())[5];
// ^^^-------- call f -> yields pointer to array of 5 ints
// ^----------- dereferene the result of f -> yields array of 5 ints
// ^^^---- access the fifth element
Now you only substitute the *
for an &
because you're returning a reference in your example.
The parameter syntax works analogously.