void foo(int &testarray[3])
is interpreted as void foo((int &)testarray[3])
due to priority. And array of references are illegal.
Whereas void foo(int (&testarray)[3])
is interpreted as you want. (reference of an array of 3 int).
void foo(int testarray[3])
is equivalent to void foo(int testarray[])
which decays to void foo(int *testarray)
. (int pointer).