1

I was using malloc() to create a 2d array to store data from the stdin. I wanted to test it out before coding specifically what is required to get a general idea. I found the following code online

int r, c;
scanf("%d%d", &r, &c);
int *arr = (int *)malloc(r * c * sizeof(int));
int i, j, count = 0;
for (i = 0; i <  r; i++)
    for (j = 0; j < c; j++)
      *(arr + i*c + j) = ++count;

for (i = 0; i <  r; i++)
    for (j = 0; j < c; j++)
        printf("%d ", *(arr + i*c + j));

The online code had hardcoded values for r and c so I changed it to a scanf to make it similar to what I would be needing later. It works well but I do not understand why I cannot use arr[i][j] instead of *(arr + i *c +j) in my code. When I tried using it i got the following error: error: subscripted value is neither array nor pointer nor vector

My understanding was that pointers and arrays are interchangeable, where am I going wrong?

omaticat
  • 96
  • 7
  • Because `arr[i]` is a scalar (you have a 1D array after all), and further indexing on a scalar makes no sense. – cs95 Oct 09 '17 at 04:33
  • "My understanding was that pointers and arrays are interchangeable, where am I going wrong?" - your understanding is wrong, pointers and arrays are not interchangeable. – Crowman Oct 09 '17 at 04:33
  • If you use e.g. `arr[i][j]` that assumes that `arr` is either an array of pointers, or an array of arrays. You have a *single* "array". You can however use `arr[i*c + j]`. – Some programmer dude Oct 09 '17 at 04:33
  • Unrelated to your problem, but [should you really cast the return of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)? – Some programmer dude Oct 09 '17 at 04:34
  • so it is not exactly a 2D array, that makes sense. Thank you guys! – omaticat Oct 09 '17 at 04:37
  • As for your understanding, an array can *decay* to a pointer to its first element, but it's not a pointer in itself. For example, if you have the definition `int a[10];` then using only `a` when a pointer is expected automatically means `&a[0]`. – Some programmer dude Oct 09 '17 at 04:41
  • thanks a lot! I have an idea for writing a code for a 2D array using malloc, hopefully it will work. Else I will try to overcome my fear of using pointers to reach values – omaticat Oct 09 '17 at 04:48
  • See https://stackoverflow.com/questions/12462615/how-do-i-correctly-set-up-access-and-free-a-multidimensional-array-in-c – Support Ukraine Oct 09 '17 at 05:51

2 Answers2

2

You can't use arr[i][j] in this code because arr points to type int rather than to int * or int[SOME_DIMENSION]. But if you want to use malloc to make a real 2-dimensional array, you can:

int (*arr)[c] = (int *)malloc(r * sizeof *arr);

Now, arr[i] has type int[c], which decays to int *, and therefore arr[i][j] is valid.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • in your code you’re allocating a variable length array, which is not permitted in ISO C, and it is the first reason why `malloc` is used instead. – NoImaginationGuy Oct 09 '17 at 05:49
  • 1
    @osnapitzkindle maybe read the ISO C standard before making such preposterous statements – M.M Oct 09 '17 at 05:52
  • I’m sorry, I’m back to the ISO C90 which is obsolete. Anyway the OP is making a question about the use of `malloc`, and using variable length arrays could make the question without any sense. – NoImaginationGuy Oct 09 '17 at 05:56
  • Even if OP were stuck with C89, I think my answer, particularly the C99+ fix for the code, clarifies how the types in the question's snippet were wrong for doing what OP wants and how correct types would make it work. (BTW if `c` happens to be a constant expression rather than a variable you can do this in C89 too.) – R.. GitHub STOP HELPING ICE Oct 09 '17 at 13:38
0

If arr is int *, then arr[i] is int.

malloc in that code is creating a one dimensional vector long r*c.

*(arr + i*c + j) can be translated to arr[i*c + j]. This means that this vector is divided in r segments long c and the i is selecting the segment, while j is the offset in the segment.

You may also use malloc to allocate a pointer array, and then malloc each pointer of the array. In that case you’d have a int ** and your method will work, but it’s strongly discouraged cause you’d have to free all the pointers in the pointer array.

NoImaginationGuy
  • 1,795
  • 14
  • 24