Pointers with multi dimensional arrays problem

I am trying to get pointers to work with multi dimensional arrays. I got it to work no problems with normal arrays but when I use pointers with multi dimensional arrays, I end up getting different values with the pointer that from the actual array. I wrote an example for this:

//Just setting up Array Sizes
#define Array1_Size 5
#define Array2_Size1 5
#define Array2_Size2 5
void setup() {

  //Begin Serial for debuging
  Serial.begin(115200);

  //Set up the array and the pointer for the array:
  uint8_t Array1[Array1_Size];
  uint8_t *Array1_Point = Array1;

  //Setting random number to the array just for something to compare:
  for (uint8_t X = 0; X < Array1_Size; X++)
    Array1[X] = random(255);

  //Printing out all of the random values we generated using the actual Array:
  Serial.println(F("Array Contents:"));
  for (uint8_t X = 0; X < Array1_Size; X++) {
    Serial.print(Array1[X]);
    if (X != Array1_Size - 1) Serial.print(",");
  }
  Serial.println();

  //Printing out all of the random values we generated using the pointer to the Array:
  //it prints out correctly just like the array
  Serial.println(F("Pointer to Array Contents:"));
  for (uint8_t X = 0; X < Array1_Size; X++) {
    Serial.print(Array1_Point[X]);
    if (X != Array1_Size - 1) Serial.print(",");
  }
  Serial.println(); Serial.println(); Serial.println();



  //Setting up MultiDimensional array and pointer, similar but slightly different:
  uint8_t Array2[Array2_Size1][Array2_Size2];
  uint8_t **Array2_Point = (uint8_t**)Array2;

  //Setting up random numbers again
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Array2[X][Y] = random(255);
    }
  }

  //Printing out all contents from actual array:
  Serial.println(F("MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(Array2[X][Y]);
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();

  //Printing out all contents from Pointer to the array:
  //This ends up printing completely different values from the actual array
  Serial.println(F("Pointer to MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(Array2_Point[X][Y]);
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();
}

void loop() {

}

And this is what I get on Serial Monitor:

Array Contents:
232,19,158,38,175
Pointer to Array Contents:
232,19,158,38,175


MultiDimensional Array Contents:
197,114,68,188,109
120,80,102,47,102
143,142,79,160,52
3,124,114,32,70
18,189,123,116,190

Pointer to MultiDimensional Array Contents:
92,169,252,250,29
238,219,240,211,131
255,207,191,29,190
173,250,221,229,191
31,227,186,230,151

Can someone please help, I want to know what I am doing wrong here.
I suspect it has something to do with how I declare the pointer or maybe how I get the address to the pointer.

A multidimensional array is just a block of variables, just like a normal array.
With a multidimensional array, the compiler knows how it is organized.
A pointer to a variable or array or multidimensional array is a pointer.

You are using a pointer to a pointer. As if there is somewhere a mystical pointer that points to the array and you only have the address of the mystical pointer. That is not true, you already know where the array is.

I recently learned a new word in the 'C' language: "decay".
See: https://forum.arduino.cc/t/pointers-question/695583/2.
Maybe that is useful for you as well.

1 Like

Following up on @ Koepel's point:

//Just setting up Array Sizes
#define Array1_Size 5
#define Array2_Size1 5
#define Array2_Size2 5
void setup() {

  //Begin Serial for debuging
  Serial.begin(115200);
  delay(1000);

  //Setting up MultiDimensional array and pointer, similar but slightly different:
  uint8_t Array2[Array2_Size1][Array2_Size2];
  uint8_t *Array2_Point = &Array2[0][0];

  //Setting up random numbers again
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Array2[X][Y] = random(255);
    }
  }

  //Printing out all contents from actual array:
  Serial.println(F("MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(Array2[X][Y]);
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();

  //Printing out all contents from Pointer to the array:
  //This ends up printing completely different values from the actual array
  Serial.println(F("Pointer to MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(Array2_Point[X * Array2_Size2 + Y]);
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();
}

void loop() {
}

MultiDimensional Array Contents:
232,19,158,38,175
197,114,68,188,109
120,80,102,47,102
143,142,79,160,52
3,124,114,32,70

Pointer to MultiDimensional Array Contents:
232,19,158,38,175
197,114,68,188,109
120,80,102,47,102
143,142,79,160,52
3,124,114,32,70

1 Like
uint8_t **Array2_Point = (uint8_t**)Array2;

    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(Array2_Point[X][Y]);

when you use a pointer as a 2 dimensional array, the compiler doesn't know the sub-dimensions of the matrix -- it doesn't know where the location of Array2 [1][0] is for example

in the following code, a pointer sequentially accesses the matrix data, but is unaware of row/column boundaries (it doesn't need to)

    uint8_t *p = & Array2 [0][0];

    Serial.println(F("Pointer to Array2 Contents:"));
    for (uint8_t X = 0; X < Array2_Size1; X++) {
        for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
            Serial.print (*p++);
            if (Y != Array2_Size2 - 1)
                Serial.print(",");
        }
        Serial.println();
    }
    Serial.println();

the output appears in row/column order because the routine above knows Array2_Size2

Pointer to Array2 Contents:
255,74,236,41,205
186,171,242,251,227
70,124,194,84,248
27,232,231,141,118
90,46,99,51,159

a pointer can be set to row R as follows
uint8_t *p = & Array2 [R][0];

Alternatives:

//Just setting up Array Sizes
#define Array1_Size 5
#define Array2_Size1 5
#define Array2_Size2 5

typedef uint8_t ArrayRow[Array2_Size2];

void setup() {

  //Begin Serial for debuging
  Serial.begin(115200);
  delay(1000);

  //Setting up MultiDimensional array and pointer, similar but slightly different:
  uint8_t Array2[Array2_Size1][Array2_Size2];
  ArrayRow *rowPointer = Array2;

  //Setting up random numbers again
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Array2[X][Y] = random(255);
    }
  }

  //Printing out all contents from actual array:
  Serial.println(F("MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(Array2[X][Y]);
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();

  //Printing out all contents from Pointer to the array:
  //This ends up printing completely different values from the actual array
  Serial.println(F("Pointer to MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(rowPointer[X][Y]);
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();
}

void loop() {
}
//Just setting up Array Sizes
#define Array1_Size 5
#define Array2_Size1 5
#define Array2_Size2 5

typedef uint8_t ArrayRow[Array2_Size2];

void setup() {

  //Begin Serial for debuging
  Serial.begin(115200);
  delay(1000);

  //Setting up MultiDimensional array and pointer, similar but slightly different:
  uint8_t Array2[Array2_Size1][Array2_Size2];
  ArrayRow *rowPointer = Array2;

  //Setting up random numbers again
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Array2[X][Y] = random(255);
    }
  }

  //Printing out all contents from actual array:
  Serial.println(F("MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(Array2[X][Y]);
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();

  //Printing out all contents from Pointer to the array:
  //This ends up printing completely different values from the actual array
  Serial.println(F("Pointer to MultiDimensional Array Contents:"));
  for (uint8_t X = 0; X < Array2_Size1; X++) {
    for (uint8_t Y = 0; Y < Array2_Size2; Y++) {
      Serial.print(*(*(rowPointer + X) + Y));
      if (Y != Array2_Size2 - 1) Serial.print(",");
    }
    Serial.println();
  }
  Serial.println();
}

void loop() {
}

Fine if sequential access is all you need. No good for random access, which is pretty much the point of an array.

of course you can use a pointer to randomly access elements of an array

int *p = & array [0];
val = p [n];

by sequential i meant as the pointer is incremented, it sequentially accesses matrix value which are ordered by columns

if the pointer is to a matrix, you can do some math to locate elements by row and column
val = p [(row * N_COL) + col];
which is of course what the compiler does

it doesn’t know where the location of Array2 [1][0] is for example

I assumed that Array2 [1][0] would be right next to Array2 [0][4] in SRAM and all it needed to do was increment the pointer by one to get to it. I do understand that if you declare a pointer to a array, it does not know the size of it, same with a two dimension array except with added matrix's

As far as I know, the compiler treats arrays as pointers and the numbers you put in the brackets tells the compiler how much to increment the pointer by and then returns the value

I think this would be the easiest simplest and best option in my case
Good thing is, this can be expanded to any multi-dimensional arrays

yes. but the compiler doesn't know that the pointer is to a matrix with 5 columns.

yes,
val = Array [(row * N_COL) + col];
is the same as
val = Array [row][col];

Requires a little more gymnastics if you want to allocate your 2-D Array dynamically: https://www.geeksforgeeks.org/dynamically-allocate-2d-array-c/

Thank you for the clarification, it really helped. I was spending way to much time trying to find (the hard way) how to get it to work. I think I understand it much better

many of us have gone through the same process

1 Like

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.