3
void print_first_n_row(double **matrix, int n, int row_size) {
 double (*abc)[row_size];
 abc=matrix;}

I am having assignment from incompatible pointer type [-Wincompatible-pointer-types] abc=matrix error. How can I solve this?

ajdfhjkshg
  • 31
  • 1
  • By changing `void print_first_n_row(double **matrix, int n, int row_size)` to `void print_first_n_row(int n, int row_size, double (*matrix)[row_size])` and accordingly modifying caller? (It depends on how the function and `abc` are used) – MikeCAT May 06 '20 at 12:30
  • 1
    I do not see why any body would vote to close this. It is a question that contains commonly encountered mysteries for any new C programmer, therefore therefore will be of interest to other new programmers. – ryyker May 06 '20 at 13:26
  • 1
    You need to show us the code that calls `print_first_n_row`, and how the parameter corresponding to `matrix` has been declared. – John Bode May 06 '20 at 13:50

4 Answers4

4

A matrix is an abstract data type. How you implement it is an implementation detail.

In this answer I detailed how you could implement such a type in C.

Multi-dimensional arrays don't really exist in C. C just have arrays of arrays, or arrays of pointers -or other types, including arrays of scalars. Check by reading n1570 (the C11 standard).

I am having assignment from incompatible pointer type [-Wincompatible-pointer-types] abc=matrix error. How can I solve this?

Either think in abstract data types terms, or read more about C dynamic memory allocation (consider using flexible array members) and about the C programming language.

You'll find many examples of matrix-related source code on github or gitlab and elsewhere.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
3

Note: This answer is just regarding the error message, not the logic behind passing pointers to a matrix.


"I am having assignment from incompatible pointer type [-Wincompatible-pointer-types] abc=matrix error. How can I solve this?"

double (*abc)[row_size]; - abc is a pointer to an array of double.

double **matrix - matrix is a pointer to a pointer to double.

There is a mismatch. * vs. **.

You can´t assign the value of a pointer to a pointer to double to a pointer to an array of double.

Change double (*abc)[row_size]; to double **abc or double (**abc)[row_size]; or just use matrix if abc isn´t needed otherwise.

2

Well, the answer is that matrix and abc have to be declared the same way. Either you need to change the prototype to

void print_first_n_row(int n, int row_size, double (*matrix)[row_size]) // row_size needs to be defined first
{
  double (*abc)[row_size] = matrix;
  ...
}

or you need to change the definition of abc to

double **abc;

It depends on how you're calling defining the parameter matrix corresponds to and how you're calling print_first_n_row.

Assuming your code looks something like:

int main( void )
{
  int rows = ...;  // assumes rows and cols are set at runtime
  int cols = ...;
  ...
  double matrix[rows][cols];
  ...
  print_first_n_rows( matrix, n, cols )
  ...
}

then the first solution is correct, and you need to change the call to

  print_first_n_rows( n, cols, matrix );
John Bode
  • 119,563
  • 19
  • 122
  • 198
1

It has been explained in detail in other answers that trying to make assignments using incompatible types is wrong. Even if the compiler did not warn you, these assignments can often result in undefined behavior. But in C, multi-dimensional arrays are stored in single contiguous blocks of memory_, eg:

in array[4][2] = {{1,2,3,4},{5,6,7,8}};

Is stored in memory as a single sequential block of locations:

|1|2|3|4|5|6|7|8|

Not as you might imagine, in multiple blocks:

|1|2|3|4|
|5|6|7|8|

It is therefore possible to create a single pointer variable that can be set to point to any location within a C array (of the same base type), and can for example be used to assign values to that array, as shown in the following adaptation using Variable Length Array:

int main(void)
{
    print_first_n_row(4,2);// params to create 4X2 array

    return 0;
}

void print_first_n_row(int r, int c) 
{
    double matrix[r][c];        //create array using Variable Length Array
    double *abc = &matrix[0][0];//create pointer of same base type
                                //and set address to pointer to point to 
                                //first location of matrix
    printf("%s", "array contents:");
    for(int i=0; i<r*c; i++)
    {
        *(abc + i) = i*i;
        printf("%0.2f,", *(abc + i));

    }
}  

Or, in keeping with your example of passing the array as an argument, as long as the types are the same, the capability of using a pointer to index through the array locations holds true as well:

Passing array argument:

void print_first_n_row(double matrix[4][2]);

int main(void)
{
    double array1[4][2] = {1,2,3,4,5,6,7,8};
    print_first_n_row(array1);

    return 0;
}

void print_first_n_row(double matrix[4][2]) 
{
    double *abc = &matrix[0][0];//create pointer of same base type
                                //and set address to pointer to point to 
                                //first location of matrix
    ...(same as first example)
ryyker
  • 22,849
  • 3
  • 43
  • 87