-1

I made a function to create a contiguous two dimensional array like this:

void** create2DArray(int row, int col, size_t s) {
    void *pool = malloc(s * row * col);
    void **array = malloc(s * row);

    if(pool==NULL || array==NULL) return NULL;

    for(int i=0;i<row;i++) {
        array[i] = pool + i * col * s;
    }

    return array;
}

The function above used like this:

int **edge_matrix = create2DArray(num_vertices, num_vertices, sizeof(int));

It works without problem. But one day, I thought that I made a mistake, and I changed a line of the code with this:

array[i * s] = pool + i * col * s;

Due to the pointer arithmetic rule, the void* will always increase by i * 1 byte. I changed it so it will increase by i * s byte like usual pointer arithmetic for non void* type. But why the first one works while the second one doesn't?

  • 3
    Because `void**` is *not* `void*`. `*array` has type `void*` (i.e. is a pointer) not `void`. Also you may want to implement a more robust error checking. – Margaret Bloom Jan 03 '17 at 11:25
  • if either `pool` or `array` were to fail to be allocated and the other to succeed, you'd never unallocate the memory of the first and end up with a memory leak. granted that's an edge case. – erik258 Jan 03 '17 at 11:29
  • There is no 2D array in your code, nor anything which can point to one! Something like `int **` (worse: `void **` is a completely different datastructure. And don't get too fancy with typecasts! Such code is hard to maintain and to understand. It is also prone to type errors. – too honest for this site Jan 03 '17 at 11:30
  • To extend my comment: A 2D array would make all this unnecessary. – too honest for this site Jan 03 '17 at 11:36
  • 1
    "Due to the pointer arithmetic rule, the `void*` will always increase by i * 1 byte " - Fyi, pointer arithmetic on `pool`, a `void*` isn't standard regardless. Some (by no means all) toolchains support it as a *non-standard* extension, [but it is *not* standard](https://stackoverflow.com/questions/3523145/pointer-arithmetic-for-void-pointer-in-c). – WhozCraig Jan 03 '17 at 11:51

1 Answers1

0

Your function does not create a 2D array, nor is the memory contiguous. You shouldn't use pointer-to-pointers for this, since there is no relation between pointer-to-pointers and 2D arrays. This is a common misunderstanding.

Furthermore, the C language does not allow pointer arithmetic on void pointers. Some compilers support that as a non-standard extension equivalent to pointer arithmetic on a character type.

At any rate, you don't even need pointer arithmetic for this. Simply do:

void* create2DArray (size_t row, size_t col, size_t item_size)
{
  return malloc (item_size * row * col);
}

Or, more meaningfully:

void create2DArray (size_t row, size_t col, (type** arr_ptr)[row][col])
{
  *arr_ptr = malloc ( sizeof type[row][col] );
}


// caller:
type (*array)[row][col];
create2DArray(row, col, &array);

Complete example here: Set pointers on Dynamic Matrix

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396