Passing “array of arrays” to a function

I want to pass a 1D array of 1D arrays to a function, but don’t know how to represent the function parameters. Also, I’m open to suggestions for improving the sketch, which is described below.

I have included an attachment of the original .ino file. Note that the original sketch is labeled "insert_row." I will change the label to "replace_row," as that more accurately depicts the function of the sketch.

The declaration of the array is, "int *arr[NO_ROW];" Clearly an array of pointers to arrays.

If you examine the sketch you will see that there is a code snippet identified that prints the values of the array. I would like to capture that snippet in a function.

The sketch objective is to replace a particular row in a 2D array with another row. The sketch does that, and prints the values and addresses for each cell of the array. I printed the addresses to verify that the 2D array has the same addresses as the replacement row (pass by reference and not by value). This can be seen by the below monitor display, which I have edited, as shown with square brackets:

Insert Row sketch
=================

Row values and addresses	[<— Row_a]
-------
0, 536871196
1, 536871200

Row values and addresses	[<— Row_b]
-------
100, 536871204
101, 536871208

Matrix values and addresses
-------
0, 536871196			[<— Row_a]
1, 536871200

100, 536871204	        [<— Row_b]
101, 536871208

0, 536871196			[<— Row_a]
1, 536871200

insert_row.zip (2.46 KB)

Don’t attach the code, just insert it here... can’t read it on mobile

The declaration of the array is, "int *arr[NO_ROW];" Clearly an array of pointers to arrays.

Clearly not. It’s an array of pointers to integral number
Only you do know if it’s only 1 int or many int being there. The compiler doesn’t

Thanks, J-M-L.

As you requested, here is the code, embedded in this post.

/*
   Replaces a row in a matrix.
     When an array is printed, both the value and address
     of each element are presented.
     
     "matrixRows" is an array of rows.  First, every row of matrixRows is 
     populated with row_a.  Then, row_b is replaced with
     the second row of matrixRows.
*/

#include "Arduino.h"
#define NO_ROW  3   // number of rows in arr;
#define NO_COL  2   // number of columns in arr;
#define ROW_TITLE "\nRow values and addresses\n-------"
#define MAT_TITLE "\nMatrix values and addresses\n-------"

int *matrixRows[NO_ROW];                 // array of pointers to rows;
int row_a[NO_COL], row_b[NO_COL]; // row arrays;
int row, col, i;


// assigns a value to each cell of the
//   1D array that is passed to it;
void setRow( int a[NO_COL], int offset) {
  for(col=0; col<NO_COL; col++)
    a[col] = col+offset;
}

// prints the value and address of each cell of the
//   1D array that is passed to it;
void printRow( int a[NO_COL]) {
  Serial.println(ROW_TITLE);
  for(col=0; col<NO_COL; col++) {
    Serial.print(a[col]);  Serial.print(", ");
    Serial.println((long)&a[col]);
  }
}

void setup() {
  delay(5000);    // needed for the serial monitor (Editor bug);
  Serial.begin(9600);
  Serial.println("Insert Row sketch\n=================");

  setRow( row_a, 0);    // define row_a;
  printRow( row_a );    // print row_a;
  setRow( row_b, 100);  // define row_b;
  printRow( row_b );    // print row_b;

  // Populate matrixRows with row_a, then replace row_b with the
  //   second row of matrixRows;
  for(row=0; row<NO_ROW; row++)
    matrixRows[row] = row_a;
  matrixRows[1] = row_b;

/******* Place the below snippet into a function, that
 *         receives matrixRows;
 */ 
        Serial.println(MAT_TITLE);
        for(row=0; row<NO_ROW; row++) {
          for(col=0; col<NO_COL; col++) {
            Serial.print(matrixRows[row][col]); Serial.print(", ");
            Serial.println((long)&matrixRows[row][col]);
          }
        Serial.println("");
        }
/* end of snippet; */
  
}

void loop() {
}
  delay(5000);    // needed for the serial monitor (Editor bug);

Serial.begin(9600);

Which Arduino are you using? Due, Leonardo, Micro? Those need a slightly different approach:

  Serial.begin(9600);
  while(!Serial && millis()<5000){
    //wait for serial monitor to connect for native-USB Arduinos
  }

I don't think you've quite got it. First you set all of the arr[] pointers to point to the same place. Then you change one [1] of them to point to a different place. So any changes to arr[0] are also going to change arr[2].

arr[] is a silly name anyway. It costs nothing to use longer names. In this case, I would use a name like matrixRows[], and for a real working program, I would give it a name related to the actual stuff it contains.

Remember [] is an operator the same way that +-/* are operators. Sometimes you need to use brackets to guide the compiler to what you want. It also documents what you intended when you wrote it. (matrixRows[row])[col] is a valid expression, equivalent to matrixRows[row][col]

*** DELETED the earlier post: I see that MorganS's comment about the need to specify the type of board is pertinent. That comment applies to the delay(5000) I need to insert in order to compensate for a bug in the serial monitor. I reported this bug in the forum. Monitor needs 5 seconds before printing - Web Editor - Arduino Forum. Sorry, MorganS for my mistake.

BTW, MorganS's suggestion to use
Serial.begin(9600);
while(!Serial && millis()<5000){
//wait for serial monitor to connect for native-USB Arduinos
}
Did not work. My original delay(5000) does work, though.

Original Post:
It’s a Zero. Why does this particular sketch care whether it’s a Zero, Due, or other Arduino?

It seems to me the sketch involves pure C language, without reference to microprocessor details.

I changed "arr" to "matrixRows," as suggested by MorganS. This revision is in the code given above.

I got it to work by using the following structure:

int *matrixRows[2]; 

void fnc( int *matrix[2] ) { ; } 

void setup() {
  fnc( matrixRows ); 
}

void loop() { ; }

In order to pass the array or pointers I used the same declaration, in the function signature, as that at the top of the above code.
.
.
Here is the revised sketch, using that new structure:

/*
   Replaces a row in a matrix.
     When an array is printed, both the value and address
     of each element are presented.
     
     "matrixRows" is an array of rows.  First, every row of 
     matrixRow is populated with row_a.  Then, the second
     row of matrixRows is replaced with row_b.
*/

#include "Arduino.h"
#define NO_ROW  3   // number of rows in arr;
#define NO_COL  2   // number of columns in arr;
#define ROW_TITLE "\nRow values and addresses\n-------"
#define MAT_TITLE "\nMatrix values and addresses\n-------"

int *matrixRows[NO_ROW];          // array of pointers to int;
int row_a[NO_COL], row_b[NO_COL]; // row arrays;
int row, col, i;


// assigns a value to each cell of the
//   1D array that is passed to it;
void setRow( int a[NO_COL], int offset) {
  for(col=0; col<NO_COL; col++)
    a[col] = col+offset;
}

// prints the value and address of each cell of the
//   1D array that is passed to it;
void printRow( int a[NO_COL]) {
  Serial.println(ROW_TITLE);
  for(col=0; col<NO_COL; col++) {
    Serial.print(a[col]);  Serial.print(", ");
    Serial.println((long)&a[col]);
  }
}

// prints the value and address of each cell of the
//   2D array that is passed to it;
void printMatrix( int *matrix[NO_ROW] ) {
  Serial.println(MAT_TITLE);
  for(row=0; row<NO_ROW; row++) {
    for(col=0; col<NO_COL; col++) {
      Serial.print( (matrix[row])[col] ); Serial.print(", ");
      Serial.println( (long) &(matrix[row])[col] );
    }
  Serial.println("");
  }
}

void setup() {
  delay(5000);    // needed for the serial monitor (Editor bug);
  Serial.begin(9600);
  Serial.println("Insert Row sketch\n=================");

  setRow( row_a, 0);    // define row_a;
  printRow( row_a );    // print row_a;
  setRow( row_b, 100);  // define row_b;
  printRow( row_b );    // print row_b;

  // Populate arr with row_a, then insert row_b into the
  //   second row of arr;
  for(row=0; row<NO_ROW; row++)
    matrixRows[row] = row_a;
  matrixRows[1] = row_b;

  // print the array of pointers to int;
  printMatrix( matrixRows );
}

void loop() {
}

It's a Zero. Why does this particular sketch care whether it's a Zero, Due, or other Arduino?

In order to print something the Serial interface has to be ready. Not all Arduino boards drive the Serial interface in the same way. Compare/contrast the Uno with the Leonardo for example.

Thanks, UKHeliBob, for your gentle comment.

Please see my above reply #4, which speaks to MorganS's comment. It appears he also thought that the reason I added the delay(5000) to my code was to allow the Arduino board time to establish the Serial interface. That is not the case. The issue is a problem in the serial monitor of the Web Editor IDE, not the serial interface of the Arduino board. The delay(5000) is not needed when the desktop IDE is used.

I tried MorganS's suggested fix, to wait for !Serial to switch, and that did not work. I also should note that my delay(5000) occurs before the Serial.begin(9600) statement executes, which shows that the !Serial test is not relevant, and which implies that the problem is with the the Web Editor IDE, and not the Serial interface of the Arduino board. My delay(5000) allows the Web Editor IDE to setup, not for the Arduino board to setup.

Ahhh "Web". I did not spot that the first time.

MorganS:
Ahhh "Web". I did not spot that the first time.

The first tome it was mentioned appears to be in reply #8 so no wonder that we did not spot it earlier.

I'm really sorry for the confusion that I created.

First, I posted a problem I was having that was really due to carelessness. I was careless because I defined a function with the wrong parameter type. Here is an simplified example of that mistake:

(a) Define a function:
void fnc (type_1 val_1) {}

(b) Invoke that function:
type_2 val_2;
fnc (val_2);

Val_2 and val_1 are different types.

Then, I did not adequately respond to reply #3, by MorganS. BTW, I first described the issue, which has been discussed by the last several posts, in Monitor needs 5 seconds before printing (Read 48 times)

Please forgive me.