1

I've searched stackoverflow and seen every combination of the words in my question, but not the question I have.

I have an array of ints, it happens to be a 2d array.

const int themap[something][something] = { {0, ...

I have a struct that I want to have a pointer to this array in my program

typedef struct {
int** mymap;
} THE_STRUCT

In my program I want to iterate over the values of the array through the struct's pointer, but my data seems to be corrupted if i try to access it through the . syntax

int value;
THE_STRUCT mystruct;
mystruct = (int**) themap;

...
//access the map data from mystruct's pointer?
value = mystruct.mymap[x][y];
//doesn't seem to return correct values

Taking the struct out of the picture the same exact function works if I directly use the array (as a global variable)

int value;
...
//access the map directly
value = themap[x][y]
//everyone is happy!

I would like to use the struct as in reality it will carry other information as well as the fact that I will need to be able to assign the pointer to other arrays with different data.

ammianus
  • 488
  • 7
  • 23

2 Answers2

5

Your two-dimensional array is not the same as an int **. If you want to store a pointer to it inside the struct, you can do something like:

const int themap[something1][something2] = { {0, ...

typedef struct {
    const int (*mymap)[something2];
} THE_STRUCT;

...

THE_STRUCT my_struct;
my_struct.mymap = themap;

...

int value = my_struct.mymap[x][y];

It is possible to use an int **, but it requires some effort:

const int themap[something1][something2] = { {0, ...
const int * themapPointerArray[something1] = {themap[0], themap[1], ..., themap[something1 - 1]};

typedef struct {
    const int **mymap;
} THE_STRUCT;

...

THE_STRUCT my_struct;
my_struct.mymap = themapPointerArray;

...

int value = my_struct.mymap[x][y];
Joshua Green
  • 1,517
  • 1
  • 10
  • 14
  • what if I don't want to hard code the array length 'something2' in the struct as it might be different? – ammianus Sep 12 '12 at 00:31
  • Then you should linearize the array -- `const int themapLinear[something1 * something2] = {0, ...}` so that you only need to store a `const int *`. You would then replace `themap[x][y]` with `themapLinear[(x * something2) + y]` and here `something2` doesn't need to be known until runtime (and can, e.g., be passed into a function). – Joshua Green Sep 12 '12 at 00:39
  • The problem is that interpreting something like `themap[x][y]`, if `themap` is a two-dimensional array, requires knowing how many elements are in each row. The compiler will need to know that at compile time. – Joshua Green Sep 12 '12 at 00:48
  • It _is_ possible to use an `int **` and I've updated my answer accordingly. – Joshua Green Sep 12 '12 at 01:04
  • thanks for the explanation, that makes sense, I could limit a fixed number of elements in each row in my case I guess, so I will try that out. Thanks to you and nneonneo for your advice. – ammianus Sep 13 '12 at 21:08
  • The solution works. However I do receivce a compiler warning: "warning: assignment from incompatible pointer type" on the line that assigns my struct's pointer to 'themap' – ammianus Sep 14 '12 at 16:48
  • That's kind of an important warning. Maybe I did something wrong, though I'm not seeing anything obvious at this late hour. Which version are you using? – Joshua Green Sep 19 '12 at 02:54
  • Do you mean the compiler version? GCC 4.5.2 – ammianus Sep 22 '12 at 17:43
  • No, are you using the code with `const int (*mymap)[something2] ` or the code with `const int **mymap`? – Joshua Green Sep 23 '12 at 14:44
  • ah ok: 'const int (*mymap)[something2]' – ammianus Sep 23 '12 at 15:28
  • I just wrote up a quick test case and got no such warnings. I can't sensibly put my test code in a comment (unfortunately) and am hesitant to update my answer after it's been accepted, but perhaps you should post your code as a new question. If there's an error, it likely lies elsewhere. – Joshua Green Sep 23 '12 at 17:21
  • 1
    Ah, good. The `const` tells the compiler that you won't modify the values and that it can assume that to be the case. It will warn you if you try. There _are_ ways around this, but it's still good to declare arrays of and pointers to `const` data if you have no need to modify the stored data, as it helps prevent bugs and makes it easier for different pieces of code to use the same array(s). – Joshua Green Sep 23 '12 at 21:30
3

A multidimensional array int [][] and a double-indirect pointer int ** are two completely different things.

A multidimensional array is, to C, a one-dimensional array indexed in a different way. Say x is int [3][4]. Then, x contains 12 sequentially-packed elements, and x[1][2] is just the 6th element of that one-dimensional array.

A double-indirect pointer treated as a 2-dimensional array is an array of pointers to arrays. So, if y is int **, then y[1][2] means "the third element of the array pointed to by the second element of y".

You cannot therefore convert between int [][] and int **, since they just represent different things (your casting of int [][] to int ** causes the integers in the int [][] array to be treated as pointers, which will inevitably crash).

Instead, you can cast int [M][N] as int (*)[N] -- a pointer to an array of N-length arrays.

nneonneo
  • 171,345
  • 36
  • 312
  • 383