I originally had this as an answer to this other question: When a function has a specific-size array parameter, why is it replaced with a pointer?, but just moved it here instead since it more-directly answers this question.
Building off of @Richard Corden's answer and @sbi's answer, here's a larger example demonstrating the principles of:
Enforcing a given function parameter input array size using a reference to an array of a given size, like this:
void foo2(uint8_t (&array)[100])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
and:
Allowing a function parameter input array of any size, by using a function template with a reference to an input array of a given template parameter size N
, like this:
template<size_t N>
void foo3(uint8_t (&array)[N])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
Looking at the full example below:
Notice how this function prototype doesn't know the array size at all! (the 100
here is simply a visual hint/reminder to the human user, but has no bearing or influence on the compiler whatsoever!):
void foo(uint8_t array[100]) {}
...this function prototype allows only input arrays of a fixed size of 100:
void foo2(uint8_t (&array)[100]) {}
...and this function template prototype allows arrays of ANY input size AND knows their size statically at compile-time (as that is how templates work):
template<size_t N>
void foo3(uint8_t (&array)[N]) {}
Here's the full example:
You can run it yourself here: https://onlinegdb.com/rkyL_tcBv.
#include <cstdint>
#include <cstdio>
void foo(uint8_t array[100])
{
// is ALWAYS sizeof(uint8_t*), which is 8!
printf("sizeof(array) = %lu\n", sizeof(array));
}
void foo2(uint8_t (&array)[100])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
template<size_t N>
void foo3(uint8_t (&array)[N])
{
printf("sizeof(array) = %lu\n", sizeof(array));
}
int main()
{
printf("Hello World\n");
printf("\n");
uint8_t a1[10];
uint8_t a2[11];
uint8_t a3[12];
// Is `sizeof(array) = 8` for all of these!
foo(a1);
foo(a2);
foo(a3);
printf("\n");
// Fails to compile for these 3! Sample error:
// > main.cpp:49:12: error: invalid initialization of reference of type ‘uint8_t (&)[100]
// > {aka unsigned char (&)[100]}’ from expression of type ‘uint8_t [10] {aka unsigned char [10]}’
// > foo2(a1);
// > ^
// foo2(a1);
// foo2(a2);
// foo2(a3);
// ------------------
// Works just fine for this one since the array `a4` has the right length!
// Is `sizeof(array) = 100`
uint8_t a4[100];
foo2(a4);
printf("\n");
foo3(a1);
foo3(a2);
foo3(a3);
foo3(a4);
printf("\n");
return 0;
}
Sample output:
(compiler warnings, referring to the sizeof
call inside foo()
):
main.cpp:26:49: warning: ‘sizeof’ on array function parameter ‘array’ will return size of ‘uint8_t* {aka unsigned char*}’ [-Wsizeof-array-argument]
main.cpp:23:27: note: declared here
(stdout "standard output"):
Hello World
sizeof(array) = 8
sizeof(array) = 8
sizeof(array) = 8
sizeof(array) = 100
sizeof(array) = 10
sizeof(array) = 11
sizeof(array) = 12
sizeof(array) = 100