1

I am trying to write a small C++ library to do simple matrix calculations. It consists of a Matrix class with static member functions altering given matrices.

I have one function which adds a scalar to each element, however the loop isn't working:

// Member function to add a scalar to the matrix
void Matrix::add_scal(double** arr, double s) {
    for (size_t x = 0; x < sizeof(arr) / sizeof(*arr); ++x) {
        Serial.println("test");
        for (size_t y = 0; y < sizeof(*arr) / sizeof(**arr); ++y) {
            arr[x][y] += s;
        }
   }
}

"Test" is only printed once and the inner loop isn't run at all. Here is the function I use to create a matrix:

double** Matrix::init(int rows, int cols) {
    double** temp = new double*[rows];
    for (int i = 0; i < rows; i++) {
        temp[i] = new double[cols];
        for (int j = 0; j < cols; j++) {
            temp[i][j] = 0.0;
        }
    }
    return temp;
}

The following two lines create a matrix and are supposed to add a scalar to it:

double** test = Matrix::init(3, 3);
Matrix::add_scal(test, 2.5);
gsamaras
  • 71,951
  • 46
  • 188
  • 305
derivmug
  • 21
  • 1
  • Ok sorry, could you please elaborate on what it does and whether I could still get the amount of elements in an array using it? – derivmug Nov 17 '18 at 16:09
  • Arrays aren't pointers and pointers aren't arrays. Use `std::array` or `std::vector` instead. Both of these have a `size()` function you can use to determine the size. – πάντα ῥεῖ Nov 17 '18 at 16:10

1 Answers1

1

The loop is not working, because sizeof() is not working as you think it does.

You are asking for the size of pointer, which is always a constant on a given machine (e.g. it is 4 in a 32bit). So, when you ask for the size of *arr, or **arr, that would be a number, irrelevant from the dimensions of the matrix!

In order to verify this yourself, print them, like this:

std::cout <<sizeof(*arr) << " " << sizeof(**arr) << std::endl; 

Read more in Is the sizeof(some pointer) always equal to four?


In order to loop over a matrix, you need to use its dimensions, rows and cols in your case, like this:

void Matrix::add_scal(double** arr, double s) {
    for (size_t x = 0; x < rows; ++x) {
        Serial.println("test");
        for (size_t y = 0; y < cols; ++y) {
            arr[x][y] += s;
        }
   }
}

PS: You dynamically allocate the matrix correctly, but do not forget to free the memory when you don't need it any more-it's a must! If you don't know how, check my dynamic 2D array in C++ .

Tip: In C++, I strongly suggest you to use std::vector, which grows and shrinks in size automatically. Moreover, it has a method called size(), which returns the size of it, so you don't need to track its size manually!

In order to create a matrix using vectors, read Vector of Vectors to create matrix.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • Thank you very much for your detailed explanation. I thought I could loop through the array like this because of this question: https://stackoverflow.com/questions/8109961/loop-through-a-multidimensional-array – derivmug Nov 17 '18 at 16:18
  • @derivmug this should give a warning: `warning: division 'sizeof (double*) / sizeof (double)' does not compute the number of array elements [-Wsizeof-pointer-div]`! You are welcome, glad I helped, and don't forget to accept my answer, if it helped! – gsamaras Nov 17 '18 at 16:23
  • @derivmug read more in [array decaying](https://stackoverflow.com/questions/1461432/what-is-array-decaying). – gsamaras Nov 18 '18 at 13:06