2 dimensional char array = char* ?

|43|error: cannot convert 'char (*)[(((sizetype)(((ssizetype)MAPY) + -1)) + 1)]' to 'char**' for argument '1' to 'void SetMap(char**, int, int)'|

If I'm reading correctly it says it tries to convert char* to char**, but wouldn't an 2-dimensional array be **?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <windows.h>
#include <math.h>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <utility>

using namespace std;

    void SetMap(char** Map, int MAPX, int MAPY){
        for(int a = 0; a<MAPX; a++){
            for(int b = 0; a<MAPY; b++){
                Map[a][b]='0';
            }
        }
        cout << "Type in the map!\n";
        for(int y = MAPY-1; y>=0; y--){
            char c[MAPX];
            for(int x = 0; x<MAPX; x++){
                c[x] = '0';
            }
            string s;
            cin >> s;
            strcpy(c, s.c_str());
            for(int x = 0; x<MAPX; x++){
                Map[x][y] = c[x];
            }
        }
    }


int main()
{
    int MAPX = 2;
    int MAPY = 2;
    cout << "Map Width:         ";
    cin >> MAPX;
    cout << "Map Height:        ";
    cin >> MAPY;
    char Map[MAPX][MAPY];
    SetMap(Map,MAPX,MAPY);

    cout << endl;
    for(int y = MAPY-1; y>=0; y--){
        for(int x = 0; x<MAPX; x++){
            cout << Map[x][y];
        }
    }

    return 0;
}
No, a multi-dimensional array is not a pointer to a pointer. Changing the definition of "SetMap()" to except a regular char pointer should fix that error.
But then I get

||In function 'void SetMap(char*, int, int)':|
|15|error: invalid types 'char[int]' for array subscript|
|28|error: invalid types 'char[int]' for array subscript|
||In function 'int main()':|
49|error: cannot convert 'char (*)[(((sizetype)(((ssizetype)MAPY) + -1)) + 1)]' to 'char*' for argument '1' to 'void SetMap(char*, int, int)'|
||=== Build finished: 3 errors, 0 warnings (0 minutes, 0 seconds) ===|

and I still get the same error, only now it's can't convert char(*)[.....] to char*
Sorry, you need to change the definition of the "SetMap()" function to except a pointer AND you actually have to pass it a pointer. Once you are inside of "SetMap()" you should also treat this as a pointer to an array. Keep in mind that a multi-dimensional array is just an abstraction, an array with a size of MAPX * MAPY is functionally the same thing.

Also you should only declare arrays with constant values. Otherwise look into dynamically allocating memory.
+1 @ Computergeek.

FWIW, I wrote an article a while back explaining the different types of 2D arrays, why they're incompatible, the syntax for each of them, why it's usually eaiser to avoid them, and alternatives to using them:

http://www.cplusplus.com/forum/articles/17108/
You misunderstand.

A 2D array is a special shorthand syntax for indexing a 1D array as if it were a 2D array.

{ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} }

Appears in memory as:

{ 1, 2, 3, 4, 5, 6, 7, 8, 9 }

But the compiler knows that the outer dimension is three elements long, so it can eyeball it like this:

{ 1, 2, 3,   4, 5, 6,   7, 8, 9 }

Now, when you ask for an element, say a[ 2 ][ 1 ], it knows that you mean the third group (index == 2 --> third group) and the second element in that group.

Unfortunately, you can only pass variable-sized multidimensional arrays to a function where any dimension may vary in size by using templates -- and this can bloat code quickly.

I recommend a combined approach.

First, we need to calculate the linear index of an element in a multidimensional array.

1
2
3
4
5
6
7
8
9
10
size_t index_2d( size_t rows, size_t cols, size_t row, size_t col )
{
  // You don't have to check this stuff... and how you do depends on you. 
  // Here I just throw an exception, but you can return (size_t)(-1) or whatever 
  // you think effective.
  if ((row > rows) or (col > cols)) throw 1;  

  // Here's our equation
  return (row * cols) + col;
}

C-style: playing compiler
Here is the function that does all the work.
This is the kind of function you want to write no matter what.
However, you must write it as if you were the compiler.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void my_fn( 
  // Here is the information the compiler knows about a 2D array:
  int    a[],   // address of first element
  size_t rows,  // number of elements per major dimension
  size_t cols ) // number of elements per minor dimension
{
  // In this example function, I wish to look at each element in the array
  for (size_t r = 0; r < rows; r++)
  {
    for (size_t c = 0; c < cols; c++)
    {
      size_t index = index_2d( a, rows, cols, r, c );
      // Now I can access the element:
      a[ index ] *= 5;
    }
  }
}


C++ style: all the fancy stuff to make it painless
What this is is a template function that converts a painless function call into the not-so-friendly function call to the function above.
Ideally, it should be compiled away so that there is absolutely no code bloat whatsoever.
1
2
3
4
5
template <size_t Rows, size_t Cols> inline
void my_fn( int (&a)[ Rows ][ Cols ] )
{
  return my_fn( &(a[0][0]), Rows, Cols );
}

Remember, you'll need to add any additional arguments to the C-style function to this C++ function as well.

Now, life is easy for the caller:

1
2
3
4
5
6
7
8
9
10
int main()
{
  int M1[ 3 ][ 4 ];
  int M2[ 5 ][ 7 ];

  my_fn( M1 );
  my_fn( M2 );

  ...
}

Hope this helps.
I think I'll make them into 1dimensional arrays since I give the MaxX and MaxY function anyways. I just hope I don't get confused. Thanks everybody :3
Topic archived. No new replies allowed.