0

I'm playing with pointers and stumbled accross this problem. Like in this question I wanted a generic method signature for function foo, therefore I chose void * input as parameter. For testing reasons I casted the void pointer to an int ** pointer to use it like an 2D array.

#include <stdio.h>
#include <stdlib.h>
void * foo(void *input, size_t mySize)
{
    for (size_t i = 0; i < mySize; ++i)
    {
        for (size_t j = 0; j < mySize; ++j)
        {
            ((int **)input)[i*mySize][j] = 10*i+j;
        }
    }
    return input;
}

int main(int argc, char const *argv[])
{
    size_t const mySize = 10;
    void * myMemory, * testPtr;

    myMemory = malloc(mySize * mySize * sizeof(int));

    testPtr = foo(myMemory, mySize);
    free(testPtr);
    return 0;
}

Now I thought that using the [] operator would be same as adding an int to the pointer, e.g. that ((int **)input[i][j] would be the same like `((int **)input)+i+j

But accessing the input array in foo segfaults and using gdb shows me

(gdb) p ((int **)input)[i][j]
Cannot access memory at address 0x0
(gdb) p ((int **)input)+i+j
$25 = (int **) 0x405260

so obviously there is a difference. And therefore I'm confused.

Jannek S.
  • 365
  • 3
  • 16
  • 2
    `((int **)input)[i*mySize][j]` I'm afraid this can hardly work. Why not simply `((int*)input)[i * mySize + j] = 10 * i + j;`? – Scheff's Cat Dec 15 '18 at 09:10
  • 1
    You need to treat it as `2d` array not use it as `2d` array. – kiran Biradar Dec 15 '18 at 09:10
  • Please, consider that `int a[A][B]` means a is an array of `int[B]`s. But, if you cast a pointer `void*` to another pointer `int**` from where (TH) the compiler should know which array dimension you have in mind... – Scheff's Cat Dec 15 '18 at 09:14
  • `((int **)input[i][j]` is a two-level pointer access, equivalent to `*(*((int**)input + i) + j)` (note that each `[]` includes a deference). You probably want `(int*)[i + j]`. – yeputons Dec 15 '18 at 09:15
  • Concerning generic function (interface): May be, you could have a look onto [`qsort()`](https://en.cppreference.com/w/c/algorithm/qsort). It's the C-ish version of a generic sort function. I mean specifically, how they describe the array and elements passed to make function "generically". There are certainly other examples in the standard C library - `qsort()` was just the first which came in my mind. – Scheff's Cat Dec 15 '18 at 09:17
  • 1
    Please read https://stackoverflow.com/questions/4470950/why-cant-we-use-double-pointer-to-represent-two-dimensional-arrays and https://stackoverflow.com/questions/7586702/is-2d-array-a-double-pointer – Ilja Everilä Dec 15 '18 at 11:07

2 Answers2

1

You allocated a one dimension array with mySize*mySize elements. int** is an array of pointers to int, what you want is

int **array2d;
int *p;
array2D = malloc(ROWS * sizeof(int*) + ROWS * COLUMNS * sizeof(int));
p = (int*) &array2d[ROWS];
for (size_t i = 0; i < ROWS; ++i)
    array2d[i] = &p[i * COLUMNS];

now array2d[row][column] can work.

Or, as already suggested, use a one dimension array and use the array[row * COLUMNS + column] formulae.

Frediano Ziglio
  • 310
  • 1
  • 6
1

While arrays and pointers are similar, they are not the same.

An array - single or multi dimensional - depicts a continuous chunk of memory, containing a specific datatype. For exampleint arr [10] declares arr as 10 continuous ints in memory. int multi_arr[5][10] declares multi_arr as 5 arrays of 10 continuous ints in memory.

Furthermore, the name arr would be the base address of this array, and passing it to a function would be the same as passing &arr[0].

But this is where the similarities end. A multi dimensional array can't (technically) be cast to a pointer-to-a-pointer and then back again.

If arr above pointed to a block of ints, then dereferencing the first dimension of int ** ptr would lead you to a block of pointers toint. Dereferencing that would not take you deeper into that block, as a multi dimensional array would, rather it could point anywhere.

levengli
  • 1,091
  • 7
  • 18