invalid conversion from 'void*' to 'float**' [-fpermissive]

Hi everyone,

this is my first try to do something with arduino. It's has the purpose to calculate the position of a robotarm.
I just need help at one of my function. Here is the code

float **Matrixmultiplikation(float MatrixA[4][4], float MatrixB[4][4]) {
    int i, k, h;
    float **ergebnis;
    float Summe = 0;
    ergebnis = malloc(sizeof(float*) * 4);

    for (i = 0; i < 4; i++) {
        ergebnis[i] = malloc(sizeof(float*) * 4);
    }
    for (i = 0; i < 4; i++) {
        for (k = 0; k < 4; k++) {
            for (h = 0; h < 4; h++) {
                Summe = Summe + MatrixA[i][h] * MatrixB[h][k];
            }
            ergebnis[i][k] = Summe;
            Summe = 0;
        }
    }
    return ergebnis;
}

Okay, it deleted my last sentence, I don't know why.
Here is the error message, that I received:
sketch_jan05a_V01:415:41: error: invalid conversion from 'void*' to 'float**' [-fpermissive]

_ ergebnis = malloc(sizeof(float*) * 4);_

  • ^*

sketch_jan05a_V01:418:48: error: invalid conversion from 'void*' to 'float*' [-fpermissive]

  • ergebnis* = malloc(sizeof(float*) * 4);

* ^*

exit status 1

invalid conversion from 'void*' to 'float**' [-fpermissive]

In Microsoft Visual Studio 2019 the whole code works. But unfortunately not here in arduino...
I want to return a 4x4-matrix. Thank you very much for your help!

Best regards,

Failimon

In Microsoft Visual Studio 2019 the whole code works.

I doubt that very much.
More when im at a real kb, if someone else doesn’t respond first.

Aren't you missing a cast in front of the malloc?

Although pointers to pointers is outside my comfort zone, I do stronly suggest that you check if the result of malloc() is not NULL.

They're only warnings. But as Awol says, a couple of simple casts will make them go away.

When you see >:( >:( >:( -fpermissive >:( >:( >:( it is never "only a warning".

Just what does -fpermissive mean?

SteveMann:
Just what does -fpermissive mean?

It's a compiler flag: C++ Dialect Options - Using the GNU Compiler Collection (GCC)

-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive will allow some nonconforming code to compile.

    ergebnis = malloc(sizeof(float*) * 4);  // missing the cast to float** on the result of malloc.

    for (i = 0; i < 4; i++) {
        ergebnis[i] = malloc(sizeof(float*) * 4); // missing the cast to float* on the result of malloc,
        // and the argument to malloc should be (sizeof(float) * 4).
    }
    // And you aren't checking the result of malloc for NULL, which is good practice

float **ergebnis; So.. What are you trying to do here? You copying some old Macintosh code? Why do you want a handle?

-jim lee

jimLee:
float **ergebnis; So.. What are you trying to do here?

OP is dynamically creating a 2-D array of floats. See Method #3 here: How to dynamically allocate a 2D array in C? - GeeksforGeeks.

gfvalvo:
OP is dynamically creating a 2-D array of floats. See Method #3 here: How to dynamically allocate a 2D array in C? - GeeksforGeeks.

OMG! How bloody complicated!

Well, have fun with that.

-jim lee

jimLee:
OMG! How bloody complicated!

How would you create a dynamically-sized array ... assuming you had to?

linked list.

In fact I do all the time : LC_baseTools/lists.h at master · leftCoast/LC_baseTools · GitHub

-jim lee

jimLee:
linked list.

A linked list is 1-D. You could have a linked list of arrays or other objects. But, you pay a performance penalty traversing it.

Getting to the last element of a 100 x 100 array implemented that way will be time-consuming.

No.. What you describe is root(D).

-jim lee

I want to return a 4x4-matrix. Thank you very much for your help!

float **Matrixmultiplikation(float MatrixA[4][4], float MatrixB[4][4])

A "float **" is NOT the same as a pointer to a 4x4 matrix of floats! Which do you actually want?
Indirect reference to a 2-d array is just a pointer to the first float, and an assumed layout in memory.

The other things I thought were wrong with the code are not so bad as I thought. It probably does work on Windows, although it's perhaps not doing what you think.

The error message you're getting is because C++ doesn't allow you to assign a void* pointer (as returned by malloc) to other types of pointer, without an explicit cast. C, on the other hand, DOES allow this.

While it is common (and often unavoidable) in C, you should never return the result of malloc or new from a function as a raw pointer in C++. It will inevitably lead to memory leaks.
In C++, you return data structures that manage the memory for you, e.g. std::vector, std::unique_ptr, Eigen::Matrix4d, etc. but never raw owning pointers.

Even in a pure C setting, I would argue that a matrix multiplication function should not allocate. The standard way is to use an output parameter for the result, this is what the traditional BLAS xGEMM routines do, for example. The calling code is responsible for allocating the storage for the result of the multiplication. It can choose to allocate it on the stack if necessary, and it can reuse other variables to limit the peak memory usage and number of allocations.
On desktop CPUs, you don't want each matrix operation to allocate memory, because allocation is slow and undeterministic, and you get slow, uncached heap memory.
On microcontrollers, you want to avoid dynamic allocations because they often lead to memory fragmentation.

As mentioned earlier, the layout of the “matrix” you're using is not actually a 2D array, it's an array of 4 pointers (float *) that point to arrays of 4 floats that might reside elsewhere in memory. It's not a contiguous area of memory, requires an additional indirection to access specific elements, and uses unnecessarily many allocations to set up.
For a 4×4 matrix, allocate an array of 16 floats instead, and index it as array[col + 4*row] or array[row + 4*col], depending on whether you're used to the C or Fortran convention (many linear algebra libraries ─ even in C and C++ ─ use Fortran conventions, i.e. column-major order, whereas 2D arrays in C and C++ are laid out in row-major order).

Finally, don't declare your arguments as float MatrixA[4][4], the compiler won't check the dimensions, you can pass an arrays with 100 rows or just 1 row as a parameter and the compiler won't even warn you.
Use a reference to an array instead. While you're at it, make them const read-only references, because you're not changing MatrixA and MatrixB.

For example:

void matmul(const float (&matrixA)[4][4], const float (&matrixB)[4][4], float (&result)[4][4]) {
  for (size_t r = 0; r < 4; ++r)
    for (size_t c = 0; c < 4; ++c)
      result[r][c] = 0;

  for (size_t r = 0; r < 4; ++r)
    for (size_t k = 0; k < 4; ++k)
      for (size_t c = 0; c < 4; ++c)
        result[r][c] += matrixA[r][k] * matrixB[k][c];
}

Example usage:

void matprint(const float (&matrix)[4][4]) {
  for (size_t r = 0; r < 4; ++r)
    for (size_t c = 0; c < 4; ++c)
      Serial.print(matrix[r][c]), Serial.print(c == 3 ? "\n" : ",\t");
}

void matmul(const float (&matrixA)[4][4], const float (&matrixB)[4][4], float (&result)[4][4]) {
  for (size_t r = 0; r < 4; ++r)
    for (size_t c = 0; c < 4; ++c)
      result[r][c] = 0;

  for (size_t r = 0; r < 4; ++r)
    for (size_t k = 0; k < 4; ++k)
      for (size_t c = 0; c < 4; ++c)
        result[r][c] += matrixA[r][k] * matrixB[k][c];
}

void setup() {
  Serial.begin(115200);
  while (!Serial);
  float matrixA[][4] {
    {2, 3, 5, 7},
    {11, 13, 17, 19},
    {23, 29, 31, 37},
    {41, 43, 47, 53},
  };
  float matrixB[][4] {
    {59, 61, 67, 71},
    {73, 79, 83, 89},
    {97, 101, 103, 107},
    {109, 113, 127, 131},
  };
  float matrixAtimesB[4][4];
  matmul(matrixA, matrixB, matrixAtimesB);
  matprint(matrixA);
  Serial.println("×");
  matprint(matrixB);
  Serial.println('=');
  matprint(matrixAtimesB);
}

void loop() {}

Pieter

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