Passing a 2D array to a function

Started by
21 comments, last by Zahlman 14 years, 1 month ago
I have a two dimensional array of chars for a map. But the maps will have varying size depending on the map currently loaded. But when I try something like: void Func(char cMap[][]); I get a lovely error (regarding the subscript of the array). What is the proper way to pass a two dimensional array that you don't know the size of to a function? Thank you! P.s. Please don't suggest a one dimensional array or for me to use boost's multi array.
Advertisement
For n dimensional array, you need to specify n-1 dimensions.
void func(char cMap[][255])
Which means hard-coding them at compile-time.

Quote:Please don't suggest a one dimensional array or for me to use boost's multi array.

I suggest one-dimensional array or boost multi-array. The reason is outlined above - C arrays are hard-coded.

Messing with multiple levels of indirection doesn't solve this problem in a useful way, at least no more than the alternatives would do better or cleaner.
Use a pointer to array instead. You could also use a pointer to pointer.
// pointer to arrayvoid Func(char *cMap[]);// or a pointer to pointervoid Func(char **cMap);
Quote:P.s. Please don't suggest a one dimensional array or for me to use boost's multi array.
Why not?

I'm assuming you're using C++ here. Even if you don't want to use Boost, I think it's generally accepted that the optimal way to handle variable-size multi-dimensional (non-jagged) arrays in C++ is by way of a single 1-d array that is then indexed appropriately.
Quote:What is the proper way to pass a two dimensional array that you don't know the size of to a function?
This sort of implies the question, 'what is the proper way to create a two-dimensional array that you don't know the size of'? You can do this by creating a dynamic array of pointers and then allocating memory for each entry in the array. Realistically this will most likely work fine, but it can introduce unnecessary overhead in terms of run-time efficiency (more memory allocations, possibly decreased locality of reference), memory usage (potentially greater fragmentation), and code maintenance (both allocating and freeing the memory become more complicated than they would be otherwise). The first two items may or may not matter in practice, but personally I'd consider the third reason to be a sufficient argument for favoring a 1-d array over a 2-d array.

If you don't want to use multi_array for some reason, it's easy enough to create a simple wrapper class or struct that stores the data in a std::vector object and provides indexed access via operator()().
I want to be able to pass game maps (of various sizes) to the drawing engine. The maps are 2D arrays. So, I can't hard code in any values because that would make the maps display improperly. When I use
void func(char **cMap);
I get the following error: cannot convert parameter 3 from 'char [30][40]' to 'char **'
Quote:Original post by bnosam
cannot convert parameter 3 from 'char [30][40]'

This looks like your dimensions are fixed at compile time at the call site. In that case, you can use a function template and pass the array by reference.
template<int height, int width>void Func(const char (&cMap)[height][width]){    // ...}
Quote:Original post by bnosam
I want to be able to pass game maps (of various sizes) to the drawing engine. The maps are 2D arrays. So, I can't hard code in any values because that would make the maps display improperly. When I use
void func(char **cMap);
I get the following error: cannot convert parameter 3 from 'char [30][40]' to 'char **'
That doesn't work because the type char[30][40] can only be converted to the type char*[40]. The two methods that match your criteria of no 1D array or no boost multi array is to either make a vector< vector<char> > or to allocate an array of char*s like this:
char **map = new char*[column];
then initialize each char* in the allocated array to like this:
for(int i = 0; i < column; i++){  map = new char[width];}
with caveats galore about dealing with allocation errors and deleting the memory when you are done with it.

edit: I forgot to say that if you allocate your array like this then you can make use the function
void func(char **cMap);

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

Quote:Original post by DevFred
Quote:Original post by bnosam
cannot convert parameter 3 from 'char [30][40]'

This looks like your dimensions are fixed at compile time at the call site. In that case, you can use a function template and pass the array by reference.
template<int height, int width>void Func(const char (&cMap)[height][width]){    // ...}
If the size is fixed that would work, but I am fairly sure that the OP will be reading this data from a file and therefore won't know the size at compile time.

C++: A Dialog | C++0x Features: Part1 (lambdas, auto, static_assert) , Part 2 (rvalue references) , Part 3 (decltype) | Write Games | Fix Your Timestep!

It sounds to me that you don't really want to be passing arrays around. What you really should be passing is a map object of some sort.
Quote:Original post by nobodynews
Quote:Original post by DevFred
Quote:Original post by bnosam
cannot convert parameter 3 from 'char [30][40]'

This looks like your dimensions are fixed at compile time at the call site. In that case, you can use a function template and pass the array by reference.
template<int height, int width>void Func(const char (&cMap)[height][width]){    // ...}
If the size is fixed that would work, but I am fairly sure that the OP will be reading this data from a file and therefore won't know the size at compile time.

Yeah, I planned on making it read map files. Would changing this to a 1D array make the entire thing a lot simpler?

This topic is closed to new replies.

Advertisement