3

Having looked around I've built a function that accepts a matrix and performs whatever it is I need on it, as follows:

float energycalc(float J, int **m, int row, int col){
...
}

Within the main the size of the array is defined and filled, however I cannot passs this to the function itself:

int matrix[row][col];
...
E=energycalc(J, matrix, row, col);

This results in a warning during compilation

"project.c:149: warning: passing argument 2 of ‘energycalc’ from incompatible pointer type project.c:53: note: expected ‘int **’ but argument is of type ‘int (*)[(long unsigned int)(col + -0x00000000000000001)]’

and leads to a segmentation fault.

Any help is greatly appreciated, thank you.

6
  • float energycalc(float J, int row, int col, int m[row][col] ){ Commented Apr 7, 2015 at 14:20
  • 2
    An array of arrays is not the same as a pointer to pointer, see e.g this old answer of mine to see why. You could possibly get by with a pointer to arrays though (e.g. int (*m)[]). Commented Apr 7, 2015 at 14:20
  • @legends2k The question was tagged with C only...I found out the hard way when Cool Guy complained about my answer. Commented Apr 7, 2015 at 14:24
  • The C duplicates: 2D array passing to a function and passing 2d arrays. Worry not, I've found 2 just by looking around, sure we could dig more if we sweat more :) Commented Apr 7, 2015 at 14:24
  • 1
    Check the dupes, you'd find more complete answers than any posted here. Commented Apr 7, 2015 at 14:27

5 Answers 5

3

The function should be declared like

float energycalc( float J, int row, int col, int ( *m )[col] );

if your compiler supports variable length arrays.

Otherwise if in declaration

int matrix[row][col];

col is some constant then the function can be declared the following way

float energycalc(float J, int m[][col], int row );

provided that constant col is defined before the function.

Your function declaration

float energycalc(float J, int **m, int row, int col);

is suitable when you have an array declared like

int * matrix[row];

and each element of the array is dynamically allocated like for example

for ( int i = 0; i < row; i++ ) matrix[i] = malloc( col * sizeof( int ) );
Sign up to request clarification or add additional context in comments.

Comments

3

If the array is declared as

int matrix[row][col];

then change the function declaration to

float energycalc(float J, int m[][col], int row, int col){

The name of a two dimensional array of type T does not decay to T**.

If col is a local variable, then you need to call the function with the col parameter before matrix. This is done so that col is visible in the function.

3 Comments

@BLUEPIXY , Sorry, I didn't understand
see DEMO error: 'col' undeclared here (not in a function)
@CoolGuy; With declaration float energycalc(float J, int m[][col], int row, int col) compiler has no idea about col and it will produce an error. You must have to place col before using it in int m[][col].
2

Passing two dimensional array to a function in C is often confusing for newbies.
The reason is that they assume arrays are pointers and having lack of understanding how arrays decays to pointer.
Always remember that when passed as an argument arrays converted to the pointer to its first element.
In function call

E = energycalc(J, matrix, row, col);  

matrix is converted to pointer to its first element which is matrix[0]. It means that passing matrix is equivalent to passing &matrix[0]. Note that the type of &matrix[0] is int(*)[col] (pointer to an array of col int) and hence is of matrix. This suggest that the second parameter of function energycalc must be of type int(*)[col]. Change the function declaration to

 float energycalc(int col, int (*m)[col], int row, float J);  

and call your function as

 E = energycalc(col, matrix, row, J); 

13 Comments

Or simply declare the pointer parameter as int m[row][col], which is more readable.
@Lundin; or int m[][col].
Indeed. But my point is: why would I would want to make my code less readable?
@Lundin; Why do you thing it will make less readable? To me int m[row][col] is less readable than int (*m)[col].
Sure they must learn the difference but even the most alert programmer will have her dull day when int(*)[col] will be less tricky, more explicit than int[row][col] which is nothing but the former in a parameter list.
|
0

I think you can do something like this in C

float function_name(int mat_width, int mat_height, float matrix[mat_width][mat_height]) {
    ... function body...
}

5 Comments

You can if mat_width and mat_heigth are compile-time constants. And if they are, they should be written in upper-case (because of the convention), and then this is the best way to do it, because it clearly and unambiguously documents the fact the function expects a pointer to a N by M matrix, as opposed to just a pointer to a random type without knowing if it's an array and by which size.
@Bregalad That's not true... You can mat_width and mat_height can be variables and you can send different values every time... I think it's not standard C but an extension.
@Bregalad These are variable-length arrays (VLAs). You might want to update your C knowledge to C99, which was released 16 years ago.
@MattHammond It is standard C.
@Lundin matrix in this answer has variably modified type. It might not point to a VLA (e.g. the function could be called from two different places, each with a normal array).
-1

A pointer-to-pointer is not an array, nor does it point to a two-dimensional array. It has nothing to do with arrays, period, so just forget you ever heard about pointer-to-pointers and arrays together.

(The confusion likely comes from the hordes of confused would-be programming teachers/authors telling everyone that they should use pointer-to-pointer when allocating dynamic 2D arrays. Which is just plain bad advice, since it will not allocate a real array allocated in adjacent memory cells, but rather a fragmented look-up table exploded in pieces all over the heap. See this for reference about how to actually allocate such arrays.)

Assuming that your compiler isn't completely ancient, simply use a variable length array (VLA), which is a feature introduced in the C language with the C99 standard.

#include <stdio.h>

void print_matrix (size_t row, size_t col, int matrix[row][col]);


int main (void)
{
  int matrix[2][3] = 
  {
    {1,2,3},
    {4,5,6}
  };

  print_matrix(2, 3, matrix);

  return 0;
}

void print_matrix (size_t row, size_t col, int matrix[row][col])
{
  for(size_t r=0; r<row; r++)
  {
    for(size_t c=0; c<col; c++)
    {
      printf("%d ", matrix[r][c]);
    }
    printf("\n");
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.