To pass a 1D array we would
void function(char arr[])
{
// do stuff to arr
}
char arr[20];
function(arr);
Note the absence of the size in function
's parameter arr[]
. This causes problems because arr
has decayed to a pointer no longer knows how big it is. You almost always have to
void function(char arr[],
size_t len) // so function knows when to stop putting stuff into arr
{
// do stuff to arr
}
A 2D array is an array of arrays, so the function needs to look like it's getting a pointer to an array of the size of the inner dimension
void function(char arr[][some_size_here],
size_t len) // so function knows how big arr's outer dimension is
{
// do stuff to arr
}
In this case some_size_here
is 20.
void function(char arr[][20],
size_t len) // so function knows how big arr's outer dimension is
{
// do stuff to arr
}
This is probably where your instructor expects you to stop. But why?
We can get sneakier and generalize the function with a template so you don't always have to pass in a 20 character inner array:
template <size_t N>
void function(char arr[][N],
size_t len) // so function knows how big arr's outer dimension is
{
// do stuff to arr
}
But if we're going to do that, we can go in all the way and template everything:
template <size_t M, size_t N>
void function(char (&arr)[M][N])
{
// do stuff to arr
}
This no longer needs the extra len
parameter because it knows the lengths, M
and N
. There is the odd wrinkle though. Since the array would decay to a pointer, you need to pass the array by reference to preserve its array-ness from decaying and collect the size of the first dimension. Or at least that's why I think you have to do it. There could be some other screwball reason that I never figured out.
Side note: This is a really good trick for determining the size of an array without using the sizeof(x)/sizeof(x[0])
trick. The template captures the size for you and you just return it. See std::size
to see this trick in action. This is safer than sizeof
because sizeof
will accept a pointer from a decayed array and provide the size of the pointer divided by the size of the first element, which is almost always wrong. The template trick will not compile if you accidentally feed in a pointer, saving you much debugging.
We can also make a structure that contains the array and pass the structure around
struct array
{
char thearray[21][20];
}
void function(array & arr)
{
// use arr.thearray
}
Here we want to pass by reference rather than by value (and this is about the only good way to pass an array without it decaying) so we won't be operating on a copy. A great many new C++ programmers get confused the first few times they accidentally pass a value they need to edit into a function by value and find that back at the caller the original value went unchanged.
Add templating to generalize the size and a few helpful operator overloads onto the array-in-a-struct
trick and you've pretty much just reinvented std::array
.
A quick note about cin>>thearray[x-1];
: It is only recently that >>
reading into a character array became a thing and prevented buffer buffer overflow. Traditionally because the array had decayed to a pointer and the length was lost, >>
would gleefully write past the end of the array and wreck havoc on the program. If your compiler is out of date, this can be one hell of a boobytrap. This is one of the many reasons std::string
comes highly recommended.