0

I am working on some computational physics problems in C and I face some confusion regarding my code. I spent the last weeks reading about C but I'm still new to this language.

I need to work on a two dimensional array. The length of each row may vary, so for example, I might want to use: create and modify a "triangle" matrix: [[0,1,2][1,2][2]].

In order to structure my code in a way that is maintainable, easy to read and modify, I wanted to move parts of the logic to a function. However, it appears to be more difficult than I expected.

I started with an approach where I create a int **matrix variable and pass it to a function, prefixing it with an ampersand and accept a three-star int: int ***, and work with the matrix as *matrix[i][j]. I couldn't get it to work, however matrix[0][i][j] worked and I just can't get my head around it. Aren't the two notions the same?

Here is my code:

void alloc_subscript_notation(int number_of_rows, int *** matrix) {
    matrix[0] = malloc(number_of_rows * sizeof(int *));
    for (int i = 0; i < number_of_rows; i++)
        matrix[0][i] = calloc((number_of_rows-i), sizeof(int));

}

void modify_subscript(int number_of_rows, int *** matrix) {
    matrix[0][0][1] = 8;  // just set a value of an element to 8, as a proof of concept
}

void subscript_notation (int number_of_rows, int *** matrix) {
    alloc_subscript_notation(number_of_rows, matrix);
    modify_subscript(number_of_rows, matrix);  // I can even modify it
}


void alloc_star_notation(int number_of_rows, int *** matrix) {
    *matrix = malloc(number_of_rows * sizeof(int *));

    for (int i = 0; i < number_of_rows; i++)
        *matrix[i] = calloc((number_of_rows-i), sizeof(int));

    printf("alloc_subscript_notation: zeros: %d, %d, %d\n",  // just a few examples
           *matrix[0][2], *matrix[1][1], *matrix[2][0]);
}

void star_notation (int number_of_rows, int *** matrix) {
    // SEGMENTATION FAULT!!!
    alloc_star_notation(number_of_rows, matrix);
}

int main (void) {
    int ** matrix;
    int number_of_rows = 3;  // it's dynamic in my program, but I use it this hard-coded value for clarity
    // I want to be able to access matrix elements here
    // All good here.
    subscript_notation(number_of_rows, &matrix);
    printf("subscript_notation ready. main: "
           " %d, %d, %d, modified: %d\n",
           matrix[0][2], matrix[1][1], matrix[2][0], matrix[0][1]);

    // Segmentation Fault
    star_notation(number_of_rows, &matrix);
}
Community
  • 1
  • 1
Vince Varga
  • 6,101
  • 6
  • 43
  • 60

4 Answers4

2

No, *matrix[i][j] and matrix[0][i][j] are not the same.

The former is identical to *(matrix[i][j]), whereas the latter is identical to (*matrix)[i][j].

Since you're trying to access the pointer which was passed to the function using the address operator, you have to use the latter version.

2501
  • 25,460
  • 4
  • 47
  • 87
2

I couldn't get it to work, however matrix[0][i][j] worked and I just can't get my head around it. Aren't the two notions the same?

No, *matrix[i][j] and matrix[0][i][j] are different things.

Given int *** matrix, then matrix[i][j] is pointer to int, and *matrix[i][j] is actually matrix[i][j][0]

artm
  • 17,291
  • 6
  • 38
  • 54
1

Just to expand the answer of @artm, you are not (strictly speaking) reserving space for a 2D array, the correct way to reserve space (without segmentation) for a 2D array in C is using a VLA:

#include <stdio.h>
#include <stdlib.h>

static void func(size_t dim, int (**matrix)[dim])
{
    *matrix = malloc(sizeof(int[dim]) * dim);
}

int main(void)
{
    size_t dim = 3;
    int (*matrix)[dim]; /* A pointer to an array of n elements */

    func(dim, &matrix);
    free(matrix);
    return 0;
}
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
0

I'd suggest you to use a contiguous block of memory to simplify tour code.

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

void alloc_subscript_notation(int number_of_rows, int number_of_cols, int **matrix)
{
    *matrix = malloc(number_of_rows * number_of_rows * sizeof(int));

    if (*matrix != NULL)
    {
       for (int i=0; i<number_of_rows; i++)
       {
           for (int j=0; j<number_of_cols; j++)
           {
              (*matrix)[(i*number_of_cols)+j] = (i*number_of_cols)+j;
           }
       }
    }
}


int main (void) {
    int *matrix;
    int number_of_rows = 3;  // it's dynamic in my program, but I use it this hard-coded value for clarity
    int number_of_cols = 3;  // it's dynamic in my program, but I use it this hard-coded value for clarity
    // I want to be able to access matrix elements here
    // All good here.
    alloc_subscript_notation(number_of_rows, number_of_cols, &matrix);

    if (matrix != NULL)
    {
       printf("subscript_notation ready. main: "
              " %d, %d, %d, modified: %d\n",
              matrix[(0*number_of_cols)+2], matrix[(1*number_of_cols)+1], matrix[(2*number_of_cols)+0], matrix[(0*number_of_cols)+1]);
    }
}
LPs
  • 16,045
  • 8
  • 30
  • 61