Thread: Matrix as a parameter to a function. What's wrong?

  1. #1
    Registered User
    Join Date
    Oct 2015
    Posts
    43

    Question Matrix as a parameter to a function. What's wrong?

    Hello everybody.
    I tried to give (by reference) a matrix as a parameter to a function with something like this:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    void func(int mat[][], int n)
    {
        int i,j;
        for (i=0;i<n;i++)
        {
            for (j=0;j<n;j++)
            {
                mat[i][j]=i+j;
                printf("%d",mat[i][j]);
            }
            printf("\n");
        }
    
    
    }
    
    
    int main()
    {
        int mat1[10][10];
        func(mat1,10);
    }
    But it doesn't work. Codeblocks says there's an error in this line:
    Code:
    void func(int mat[][], int n)
    Might anyone tell me what's wrong, please?

    Also, if I try with this code:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    void func(int *mat[], int n)
    {
        int i,j;
        for (i=0;i<n;i++)
        {
            for (j=0;j<n;j++)
            {
                mat[i][j]=i+j;
                printf("%d",mat[i][j]);
            }
            printf("\n");
        }
    
    
    }
    
    
    int main()
    {
        int mat1[10][10];
        func(mat1,10);
    }
    (I've changed the parameter type of the function with a vector of pointers to int).
    It builds correctly but crashes as soon as the program starts. Why?
    Last edited by sleax; 10-25-2015 at 05:11 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    You can't leave all the dimensions empty.

    You need
    void func(int mat[][10], int n)

    Although your compiler might let you use
    void func(int mat[n][n], int n)

    Or would you have to write
    void func(int n, int mat[n][n])
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2015
    Posts
    43
    Thank you, Salen.
    So, I just tried this:
    Code:
    void func(int mat[][10], int n)
    and it works fine.
    But this
    Code:
    void func(int mat[10][], int n)
    doesn't work. Why is that?

  4. #4
    misoturbutc Hodor's Avatar
    Join Date
    Nov 2013
    Posts
    1,787
    An imaginary situation:

    Code:
    Given int mat[rows][cols]; with rows = cols = 4;
    
    Then it looks something like this:
    
                   COLUMN
              0    1    2    3
            +----+----+----+----+
          0 | 0  | 1  | 2  | 3  |
            +----+----+----+----+
    R     1 | 4  | 5  | 6  |  7 |
    O       +----+----+----+----+
    W     2 | 8  | 9  | 10 | 11 |
            +----+----+----+----+
          3 | 12 | 13 | 14 | 15 |
            +----+----+----+----+
            
    The numbers inside the "cells" are the index if the matrix was a single-dimension rather than 2.
    So, the formula for calculating the index (number inside the cell) is: ?????    formula (A)
    
    If the array is flattened to a single dimension, how much information does the compiler need to be
    able to compute formula (A)?
            
    +----+----+----+----+----+        +----+
    |  0 |  1 |  2 |  3 |  4 |        | 15 |
    +----+----+----+----+----+ ...... +----+
    
    Is the number of rows required to compute the formula?

  5. #5
    Ticked and off
    Join Date
    Oct 2011
    Location
    La-la land
    Posts
    1,728
    If you work with matrices, I recommend you get into the habit of using a struct for it.

    I've posted my own preferred one here several times already, but here goes again!

    First, I keep the actual matrix data in a separate structure. The matrices refer to this structure (I call this the owner), and it records the number of matrices referring to it. As long as you destroy each matrix after you no longer need it, the owners get destroyed then too, and you don't need to worry about the cases where two of those matrices referred to the same data; it all gets handled correctly with very little code.

    The actual matrix has both row and column strides; this means the matrix elements do not need to be consecutive in memory either way, as long as their addresses are regular. You can make one that is compatible with standard C two-dimensional arrays, but you can also transpose a matrix without copying any data.
    Code:
    struct owner {
        long   refcount; /* Number of matrices using this data */
        double data[];
    };
    
    typedef struct matrix  matrix;
    struct matrix {
        int           rows;
        int           cols;
        long          rowstride;
        long          colstride;
        struct owner *owner;
        double       *origin;
    };
    #define MATRIX_NONE { 0, 0, 0L, 0L, NULL, NULL }
    To access the element at row r, column c, in matrix m (with m declared as matrix m;), you use
    m.origin[r*m.rowstride + c*m.colstride]
    If m is a pointer to a matrix, matrix *m;, you use
    m->origin[r*m->rowstride + c*m->colstride]
    In both cases 0 ≤ r < rows, 0 ≤ c < cols.

    I don't mind posting my functions for creating and managing such structures, but I guess those are really not that useful for beginner programmers.

    Instead, you can just supply your functions with a pointer to the initial element (I call this origin), number of rows (rows), number of columns (cols), the number of positions between elements on the same column but successive rows (rowstride), and the number of positions between elements on the same row but successive columns (colstride). For example,
    Code:
    int do_something(int *const origin,
                    const int rows, const int cols,
                    const int rowstride, const int colstride)
    {
        /* element[r][c] == origin[ r * rowstride + c * colstride ],
         * and 0 <= r && 0 <= c && r < rows && c < cols.
        */
        return 0;
    }
    but note that if you intend the code to work for large matrices, rowstride and colstride should be of type long (or ssize_t), as int is not large enough to hold array sizes on all architectures.

    In essence, colstride is the number of elements to go forward in the array (negative if backwards) to get to the next column on the same row.

    rowstride is the number of elements to go forward in the array (negative if backwards) to get to the next row on the same column.

    Because C uses row-major order, for normal 2D arrays rowstride is the number of elements on each row (array width), and colstride is 1.

    Here is an example of how to use the above:
    Code:
        int matrix[9][7];
    
        do_something((int *)matrix, 9, 7,  7, 1);
    Or, if you wish to only work on the 3-row, 2-column submatrix starting at the second row, third column,
    Code:
        do_something((int *)(&matrix[1][2]), 3, 2, 7, 1);
    Or, if you wanted to work on the transpose of the submatrix,
    Code:
        do_something((int *)(&matrix[1][2]), 2, 3, 1, 7);
    The options are, well, not limitless, but huge! For a last example, this works on the one-column, 7-row matrix composed of the diagonal elements in the matrix:
    Code:
        do_something((int *)matrix, 7, 1, 8, 0);
    That is, colstride is zero because there is just one column, and rowstride is large enough to move one row down and one column right, i.e. number of columns in the array + 1.

    The only downside of having both colstride and rowstride is a slight overhead in element access; instead of one multiplication, we do two. In most situations it is not really even measurable, and in the rest, the benefits/versatility outweigh that small cost.

  6. #6
    Registered User
    Join Date
    Oct 2015
    Posts
    43
    Thank you all! I got it.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 05-19-2014, 07:32 PM
  2. function parameter/ function argument
    By codecaine_21 in forum C Programming
    Replies: 2
    Last Post: 09-24-2010, 08:09 PM
  3. how to add a parameter to the function
    By jayfriend in forum C Programming
    Replies: 5
    Last Post: 01-16-2007, 09:31 PM
  4. Replies: 13
    Last Post: 08-24-2006, 12:22 AM
  5. Parameter in a function
    By cpluspluser in forum C++ Programming
    Replies: 2
    Last Post: 04-09-2003, 07:48 PM

Tags for this Thread