views:

202

answers:

4

I'm getting confused by pointers in objective-c.

Basically I have a bunch of static data in my code.

static int dataSet0[2][2] = {{0, 1}, {2, 3}};
static int dataSet1[2][2] = {{4, 5}, {6, 7}};

And I want to have an array to index it all.

dataSets[0]; //Would give me dataSet0...

What should the type of dataSets be, and how would I initialize it?

+1  A: 

Your index array would be an array of pointers to pointers to int.

So the declaration would look like:

int ** dataset[numOfDataSets] = {dataSet0, dataSet1, ...}

Remember that objective-c is a proper superset of ansi-c, and this question in particular is about the c language, really.

Edit: It's important to remember that in C, arrays are essentially just pointers, and two-dimensional arrays are pointers to pointers.

Edit 2: I think act actually I muffed operator precedence. Should be:

int (** dataset)[numOfDataSets] = {dataSet0, dataSet1, ...}
Rob Lachlan
That does work, thanks. However, it gives a warning: `initialization from incompatible pointer type`. Any idea how to clear that up?
Justin
@Justin: I think that I made an operator precedence error. See the edited solution.
Rob Lachlan
dataSet0 and dataSet1 aren't actually arrays of pointers (so int ** won't work) - they're just flat arrays with convenient access.
dbarker
@dbarker is right. The way dataset0 and dataset1 were declared, the compiler needs to know at least the row width for the dataset arrays. And they all have to be the same.
sblom
+3  A: 

Pointers to multi-dimensional arrays can be tricky. A typedef can help:

typedef int (*DataSetType)[2];
DataSetType dataSets[] = { dataSet0, dataSet1 /* and so on*/ };
Jon Reid
+2  A: 

You could use an NSPointerArray.

Carl Norum
Only Obj-C answer so far. :)
sblom
+2  A: 

While it's laid out the same in memory, a pointer to a multidimensional array is different than a pointer to a flat array. The compiler has to convert the [][] index to a flat array index for any multidimensional arrays. Can't mix the two or the distinction for the compiler is lost. You can either use all flat arrays:

  static int dataSet00[2] = {0,1};
  static int dataSet01[2] = {2,3};
  static int * dataSet0[2] = {dataSet00, dataSet01};

  static int dataSet10[2] = {4, 5};
  static int dataSet11[2] = {6, 7};
  static int * dataSet1[2] = {dataSet10, dataSet11};

  static int ** dataSets[2] = {dataSet0, dataSet1};

or one big multidimensional array:

  static int dataSets[2][2][2] = {{{0,1},{2,3}},{{4,5},{6,7}}};

but not a combination of the two unless you clue the compiler in by declaring a special datatype per Jon's suggestion.

dbarker
It's _not_ laid out the same in memory. In a multidimensional array, it's all in contiguous memory, and the compiler uses knowledge of row-length to determine the offset for the pointer arithmetic. With your other approach (int * and int **) you actually have to dereference pointers on each level of indexing.
sblom
@sblom is right that they're structurally very different. Strangely, though, the rest of post (examples and all) is otherwise 100% correct as far as I can tell.
Chuck
ah - yes, the two approaches would definitely be laid out differently. That first sentence says that while {{1,2},{3,4}} and {1,2,3,4} are laid out the same they have an important difference at compile time which prevents them from being assigned interchangeably.
dbarker