Home > Software design >  C allocate 'array pointer' inside a function
C allocate 'array pointer' inside a function

Time:01-24

Related to dynamic allocation inside a function, most questions & answers are based on double pointers.

But I was recommended to avoid using double pointer unless I have to, so I want to allocate a 'array pointer' (not 'array of pointer') and hide it inside a function.

int (*arr1d) = calloc(dim1, sizeof(*arr1d));
int (*arr2d)[dim2] = calloc(dim1, sizeof(*arr2d));

Since the above lines are the typical dynamic-allocation of pointer of array, I tried the following.

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

int allocateArray1D(int n, int **arr) {
    *arr = calloc(n, sizeof(*arr));
    for (int i = 0; i < n; i  ) {
        (*arr)[i] = i;
    }

    return 0;
}

int allocateArray2D(int nx, int ny, int *(*arr)[ny]) {
    *arr[ny] = calloc(nx, sizeof(*arr));
    for (int i = 0; i < nx; i  ) {
        for (int j = 0; j < ny; j  ) {
            (*arr)[i][j] = 10 * i   j;
        }
    }

    return 0;
}

int main() {
    int nx = 3;
    int ny = 2;

    int *arr1d = NULL;                  // (1)
    allocateArray1D(nx, &arr1d);

    int(*arr2d)[ny] = NULL;             // (2)
    allocateArray2D(nx, ny, &arr2d);

    for (int i = 0; i < nx; i  ) {
        printf("arr1d[%d] = %d \n", i, arr1d[i]);
    }
    printf("\n");

    printf("arr2d \n");
    for (int i = 0; i < nx; i  ) {
        for (int j = 0; j < ny; j  ) {
            printf(" %d ", arr2d[i][j]);
        }
        printf("\n");
    }

    return 0;
}

And the error message already comes during the compilation.

03.c(32): warning #167: argument of type "int (**)[ny]" is incompatible with parameter of type "int *(*)[*]"
    allocateArray2D(nx, ny, &arr2d);
                            ^

It is evident from the error message that it has been messed up with the argument types (that I wrote as int *(*arr)[ny]) but what should I have to put there? I tried some variants like int *((*arr)[ny]), but didn't work).

And if I remove the 2D parts, then the code well compiles, and run as expected. But I wonder if this is the right practice, at least for 1D case since there are many examples where the code behaves as expected, but in fact there were wrong or un-standard lines.

Also, the above code is not satisfactory in the first place. I want to even remove the lines in main() that I marked as (1) and (2).

So in the end I want a code something like this, but all with the 'array pointers'.

int **arr2d;
allocateArray2D(nx, ny, arr2d);

How could this be done?

CodePudding user response:

You need to pass the array pointer by reference (not pass an array pointer to an array of int*):
int *(*arr)[ny] -> int (**arr)[ny]

The function becomes:

int allocateArray2D(int nx, int ny, int (**arr)[ny]) {
    *arr = calloc(nx, sizeof(int[ny])); // or sizeof(**arr)
    for (int i = 0; i < nx; i  ) {
        for (int j = 0; j < ny; j  ) {
            (*arr)[i][j] = 10 * i   j;
        }
    }
    return 0;
}

For details, check out Correctly allocating multi-dimensional arrays

Best practices with malloc family is to always check if allocation succeeded and always free() at the end of the program.


As a micro-optimization, I'd rather recommend to use *arr = malloc( sizeof(int[nx][ny]) );, since calloc just creates pointless overhead bloat in the form of zero initialization. There's no use of it here since every item is assigned explicitly anyway.

CodePudding user response:

  1. Wrong parameter type
  2. Strange allocation
  3. Wrong size type
  4. I would return the array as void * too (at least to check if allocation did not fail).
void *allocateArray2D(size_t nx, size_t ny, int (**arr)[ny]) {
    //*arr = calloc(nx, sizeof(**arr)); calloc is not needed here as you assign values to the array
    *arr = malloc(nx * sizeof(**arr));
    for (size_t i = 0; i < nx; i  ) {
        for (size_t j = 0; j < ny; j  ) {
            (*arr)[i][j] = 10 * i   j;
        }
    }

    return *arr;
}
  •  Tags:  
  • c
  • Related