3

So I read dozens of examples of passing an 2D array pointer to function to get/change values of that array in function. But is it possible to create (allocate memory) inside the function. Something like this:

#include <stdio.h>

void createArr(int** arrPtr, int x, int y);

int main() {

    int x, y;       //Dimension
    int i, j;       //Loop indexes
    int** arr;      //2D array pointer
    arr = NULL;
    x=3;
    y=4;

    createArr(arr, x, y);

    for (i = 0; i < x; ++i) {
        for (j = 0; j < y; ++j) {
            printf("%d\n", arr[i][j]);
        }
        printf("\n");
    }
    _getch();    
}

void createArr(int** arrPtr, int x, int y) {
    int i, j;       //Loop indexes
    arrPtr = malloc(x*sizeof(int*));
    for (i = 0; i < x; ++i)
        arrPtr[i] = malloc(y*sizeof(int));

    for (i = 0; i < x; ++i) {
        for (j = 0; j < y; ++j) {
            arrPtr[i][j] = i + j;
        }
    }    
}
4
  • There are no array pointers in your code, nor any 2D arrays. Commented Apr 20, 2016 at 13:04
  • @Martin Could you tell me how? Commented Apr 20, 2016 at 13:06
  • @Lundin Ok so there is pointer to pointer to int, but it can be used in as a pointer to 2Dim array, right? Commented Apr 20, 2016 at 13:07
  • @Marcin No, it cannot. It's a common mistake, you've been learning from bad sources. I'll post an answer. Commented Apr 20, 2016 at 13:11

3 Answers 3

3

Forget about pointer-to-pointers. They have nothing to do with 2D arrays.

How to do it correctly: How do I correctly set up, access, and free a multidimensional array in C?.

One of many reasons why it is wrong to use pointer-to-pointer: Why do I need to use type** to point to type*?.

Example of how you could do it properly:

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


void* create_2D_array (size_t x, size_t y)
{
  int (*array)[y] = malloc( sizeof(int[x][y]) );

  for (size_t i = 0; i < x; ++i) 
  {
    for (size_t j = 0; j < y; ++j) 
    {
      array[i][j] = (int)(i + j);
    }
  }

  return array;
}

void print_2D_array (size_t x, size_t y, int array[x][y])
{
  for (size_t i = 0; i < x; ++i) 
  {
    for (size_t j = 0; j < y; ++j) 
    {
      printf("%d ", array[i][j]);
    }
    printf("\n");
  }
}


int main (void)
{
  size_t x = 5;
  size_t y = 3;

  int (*arr_2D)[y];

  arr_2D = create_2D_array(x, y);

  print_2D_array(x, y, arr_2D);

  free(arr_2D);

  return 0;
}
Sign up to request clarification or add additional context in comments.

7 Comments

When I try to use your version it say that : size_t y expression must have constant value. So you can't make arrays like this dynamically (as I said...)
@Marcin I did compile and test this code. You must use a compiler made after the year 1999 (why wouldn't you?). For example GCC. You can tell GCC to be a C compiler with the compiler options gcc -std=c11 -pedantic-errors.
I spent whole day today and can't figure out one think. Everything from your example seams to work but I can't figure out this. If I print table by function print2DArray(xDim, yDim, arr); I get all elements so it works fine. If I print one element like this printf( "%d\n", arr[0][0]) it is fine to. BUT if I print like this printf( "%d\n",old[1][1]); or any other value different than 0, I get segmentation fault. Please help me.
@Marcin What is "old"?
Sorry. "old" is the name of array that I use in my code, but here i pasted it as arr. So it should be printf( "%d\n",arr[1][1]). The names are fine in code.
|
2

Yes, passing a pointer to int ** (but 3 stars is considered bad style), I suggest to return an allocated variable from your function:

int **createArr(int x, int y)
{
    int **arrPtr;
    int i, j;       //Loop indexes

    arrPtr = malloc(x*sizeof(int*));
    if (arrPtr == NULL) { /* always check the return of malloc */
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    for (i = 0; i < x; ++i) {
        arrPtr[i] = malloc(y*sizeof(int));
        if (arrPtr[i] == NULL) {
            perror("malloc");
            exit(EXIT_FAILURE);
        }
    }
    for (i = 0; i < x; ++i) {
        for (j = 0; j < y; ++j) {
            arrPtr[i][j] = i + j;
        }
    }
    return arrPtr;   
}

Call it using:

arr = createArr(x, y);

13 Comments

You should check all return values of malloc, not only the first one.
There is no reason to create a segmented pointer-to-pointer thing. Instead, when you want a 2D array, use a 2D array.
Soo.. I can do it like this: void createArr(int*** arrPtr, int x, int y); And here arrPtr is a pointer which point to a **int, which can contain addresses for arrays. But it looks bad. And another way ,more elegant, is the one you showed. Thank you very much for quick answers!
@Marcin It looks bad because it is bad. You shouldn't use any pointer-to-pointer to begin with. You should use real 2D arrays, assuming 2D arrays is what you want.
@Lundin But I have to create this array dynamically (don't know the dimension before runtime), so I have to do it like this.
|
0

Yes, an array can be initialized this way. As long as you pass a pointer, the memory address should remain the same. So, if you assign anything to the pointer it will valid.

Think of an a[] as a* pointer to the first element

a [][] will be a** pointer to a pointer of the first element or a pointer to the first array (first row of a table)

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.