0

I have created two matrices in C with the following code:

static allocation method

int data[NMAX][NMAX]; // define NMAX 10 is in header

dynamic allocation method

int** data = (int**) malloc(sizeof(int*) * N);
        for (int i = 0; i < N; i++) {
            data[i] = (int*) malloc(sizeof(int) * M);
        }

now i want to insert data into them with ONE function like so:

int inputMatrix(int **data, int N, int M) { ... }

How can i make the same function declaration work for both array types? Currently it outputs

expected 'int **' but argument is of type 'int ** (*)[10]'

I have tried creating the static array like this:

        int* data[NMAX];
        for (int i = 0; i < N; i++) {
            data[i] = (int[NMAX]) {};
        }

but this code produces a matrix with every line being the same after I input numbers into it

Zelassin
  • 3
  • 2
  • 2
    Only the first one is a 2D array (array of arrays). The second one is an array of pointers to arrays. They are different data structures. – user253751 Jul 13 '22 at 13:59
  • Side note: Casting results of `malloc()` family is [considered as a bad practice](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc). – MikeCAT Jul 13 '22 at 14:01
  • I didn't even bother checking if it's necessary to cast the malloc result, i just copypasted that line from the tutorial i'm currently following. I will not do it again then, thanks – Zelassin Jul 13 '22 at 14:06
  • Check out [Correctly allocating multi-dimensional arrays](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). – Lundin Jul 13 '22 at 15:03

2 Answers2

0

The function inputMatrix will take an array whose elements are pointers to int, so you can create an array that holds pointers to each rows of statically allocated array and pass that to the function.

Construction of the pointer array can be done like this:

int data[NMAX][NMAX];
int *pdata[NMAX]; // array of pointers
for (int i = 0; i < N; i++) {
    pdata[i] = data[i]; // the array data[i] is converted to pointers to their first elements here
}
MikeCAT
  • 73,922
  • 11
  • 45
  • 70
  • Thanks, this does work. I wonder why what i tried in the last code snippet didn't work and changing one line in the matrix would change all of them. I assume every line was created as a pointer to the same memory block, but i didn't expect it to work that way – Zelassin Jul 13 '22 at 14:12
0

##EDI##

You array pointers

int arr[10][5];

int main(void)
{
    srand(time(NULL));
    fillArray(5, 10, arr);
    printArray(5, 10, arr);
}

See the implementations below https://godbolt.org/z/M6GhrEojn

Do not use arrays of pointers. Use array pointers instead. You remove one level of indirection and you can allocate and free it using one function call. As the whole array is a contignous chunk of memory it is much easier for processor yo use the cache.

void *allocateArray(size_t rows, size_t cols)
{
    int (*a)[cols] = malloc(rows * sizeof(*a));
    return a;
}

and example usage:

void fillArray(size_t cols, size_t rows, int (*arr)[cols])
{
    for(size_t row = 0; row < rows; row++)
        for(size_t col = 0; col < cols; col++)
            arr[row][col] = rand();
}

void printArray(size_t cols, size_t rows, int (*arr)[cols])
{
    for(size_t row = 0; row < rows; row++)
    {
        for(size_t col = 0; col < cols; col++)
            printf("[%02zu][%02zu]%d,\t", row, col, arr[row][col]);
        printf("\n");
    }
}


int main(void)
{
    size_t cols, rows;
    scanf("%zu,%zu", &rows, &cols);
    printf("rows:%zu, cols:%zu", rows, cols);
    int (*array)[cols] = allocateArray(rows, cols);
    srand(time(NULL));
    printf("%p\n", array);
    if(array) 
    {
        fillArray(rows, cols, array);
        printArray(rows, cols, array);
    }
    free(array);
}
0___________
  • 60,014
  • 4
  • 34
  • 74
  • Yes, i have this in my code as well, i actually have four different ways to create a matrix, this is one of them too. Just trying to make all of them work with the same input function and only the static array was a problem – Zelassin Jul 13 '22 at 14:19
  • He is returning a `void *` because his examples uses a variable-length array and you can not return a VLA from a funcion. Good to say that VLAs are optional since C11. – David Ranieri Jul 13 '22 at 14:21
  • @Zelassin do not use int ** only array pointer - see amended answer – 0___________ Jul 13 '22 at 14:28
  • 1
    @DavidRanieri, pointers to VLA *will* be mandatory feature in upcomming C23 standard – tstanisl Jul 13 '22 at 22:11
  • @tstanisl woow thats nice to hear, I asked about this possibility some years ago: https://stackoverflow.com/q/53359275/1606345 – David Ranieri Jul 14 '22 at 05:31