7

Let a be an one dimensional array of 10 integers as shown below

int a[10];

and for above declared array the expression

a[i]

is evaluated as *(a+i) and gives the value stored at the ith index,e.g.

int a[5]={1,2,3,4,5};

here a[3] is evaluated as *(a+3) which is equal to 4 ,i.e. the value of element stored at 3rd index of array a. But in case of a 2D array like this one

int b[2][3]={ {1,2,3},{4,5,6} };

(here I am thinking of 2D array b as array of 1D arrays,i.e. b is a 1D array having 2 elements,each element itself being an 1D array of 3 int) if we use single subscript operator with array name as

b[i]

the above expression for i=1 gives address where the element 4 is stored,so

  1. How is the expression b[i] evaluated in case when b is 2D array?
  2. How is the expression b[i][j] evaluated in case when b is 2D array?
  3. How to access elements of a Multi-dimensional Array in C using pointers. Here I would like to know about how compiler treats a Multi-dimensional Array internally ?
  4. What does b evaluate to if b is a 2D array?
  • 2
    Consider the two dimensional array as array of arrays. First index lets you the access the array while the second one lets you access the value in that array. – GAURANG VYAS May 11 '17 at 06:03
  • 2D array `a[i][j] = *(*(a + i) + j);` which is equivalent to `*(*(a + j) + i);` (although the first form preserves the original index order), You can do this for any number of dimensions, but order becomes important. – David C. Rankin May 11 '17 at 06:05
  • b[1] gives the address of the second array. Which is also the address of the first element of the second array. – Ajay Brahmakshatriya May 11 '17 at 06:05
  • 1
    @DavidC.Rankin I am not sure if the second one is correct. consider the simple case `i = 0; j = 1`.`a[i][j]` will be `2` in the question and `*(*(a + j) + i)` will be `4` – Ajay Brahmakshatriya May 11 '17 at 06:08
  • and how are those expressions evaluated? –  May 11 '17 at 06:10
  • @AjayBrahmakshatriya Are you sure? `*(*(a + 0) + 1) = *(a + 1)` and `*(*(a + 1) + 0) = *(a + 1)`.. Your math any different? Recall `*(a + 0) = a` – David C. Rankin May 11 '17 at 06:10
  • @DavidC.Rankin okay simple question according to you - `a[i][j]` = `*(*(a + i) + j)` = `*(*(a + j) + i)` = `a[j][i]` (I applied the first rule again). Do you mean to imply that `a[x][y]` = `a[y][x]` ? – Ajay Brahmakshatriya May 11 '17 at 06:19
  • @DavidC.Rankin Now the problem with your argument is that `*(*(a + 1) + 0) =/= *(a + 1)`. the final value will be `a + 3`. I think you are confusing the types of `a` and `*a` – Ajay Brahmakshatriya May 11 '17 at 06:22
  • @DavidC.Rankin Check this [Demo](https://ideone.com/iqS964) – Ajay Brahmakshatriya May 11 '17 at 06:26
  • No, when you are talking about an array `a = &a[0] = &(*(a + 0)) = (a + 0) = a`. You are correct regarding the 2D array, the order of offset matters, which row, which column (e.g. `a[0][3] is not a[3][0]`, but as a general statement you are computing an offset and must be conscious of the order. I apologize for the inartful way it came across. (good exercise either way) That was the purpose of the first statement comment *(although the first form preserves the original index order)*. – David C. Rankin May 11 '17 at 06:31
  • @DavidC.Rankin I am always happy with a good discussion. I was just trying to avoid any confusion for OP or any other readers. – Ajay Brahmakshatriya May 11 '17 at 06:36
  • Yes, re-reading the entire flow, my intent that the (...initial order) be understood that the remainder was addressing the offset w/o preserving row/col order *is not clear*. Good job with making it clear to prevent confusion. – David C. Rankin May 11 '17 at 06:41

2 Answers2

5

here i am thinking of 2D array b as array of 1D arrays

That's the correct way to approach this, because that's indeed what it is. The C standard does not actually specify multi-dimensional arrays as some special case, but they are rather possible because an array is a type like any other. So we can have an array of arrays.

  1. How is the expression b[i] evaluated in case when b is 2D array?
    ...
    1. What does b evaluate to if b is a 2D array?

As for any array, b when used in an expression, decays into a pointer to the first element. b[i] is therefore equivalent to *(b+i), as for any other array expression.

In this case b decays into an array pointer of type int(*)[3].

  1. How is the expression b[i][j] evaluated in case when b is 2D array?
  • b is used in an expression, so in this expression it decays into a pointer to the first element, which is an array pointer to the first array.
  • b[i] causes pointer arithmetic to get applied to the array pointer, equivalent to *(b+i). This gives array number i.
  • At this position we have a 1D array of type int[3]. Since this array is part of another array, it has no identifier by itself. But for the sake of illustration, lets pretend it gets a temporary name "tmp". We would then have the expression tmp[j], which as always decays into *(tmp+j), resulting in an int.

Essentially the whole expression can be treated as *(*(b+i) + j).

  1. How to access elements of a Multi-dimensional Array in C using pointers.Here i would like to know about how compiler treats a Multi-dimensional Array internally ?

As explained above, it treats it as an array of arrays. For example, you can iterate over a 2D array by using array pointers:

#include <stdio.h>

void print_array (int array[3])
{
  printf("%d %d %d\n", array[0], array[1], array[2]);
}

int main (void)
{
  int b[2][3]={ {1,2,3},{4,5,6} };
  const size_t b_size = sizeof b / sizeof *b;

  for(int(*ptr)[3] = b; ptr < b+b_size; ptr++)
  {
    print_array(*ptr);
  }
}
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • 1
    As for any array, b when used in an expression, decays into a pointer to the first element. Here what i understand by decaying is that when array name is used in expressions, array name is then treated as pointer to the first element of array itself. Is it correct, also can you please elaborate what is meant by decaying here? –  May 12 '17 at 03:11
  • 2
    @amanawasthi Yes that is correct. This is why arrays and pointers are often mixed up, since arrays turn into pointers in many cases. – Lundin May 12 '17 at 06:32
4

A 2D array can be thought of as an array of arrays, or in other words, an array which has arrays as elements. For example,

int x[10];

is an array containing 10 ints. Similarly,

int x[10][10];

can be considered as an array which contains 10 arrays, each of which contains 10 ints.


How is the expression b[i] evaluated in case when b is 2D array?

When b is a 2D array, b is also a pointer to the first element of the array. Therefore, b[i] is evaluated as *(b+i) and gives the address of the ith element (in other words, array) of b, which is the same with the address of the first element of the ith array.

How is the expression b[i][j] evaluated in case when b is 2D array?

b[i][j] is evaluated as *(*(b+i) + j). This indicates choosing the ith element of b (in other words, the ith row), and from this, choosing the jth element (in other words, the jth column).

How to access elements of a Multi-dimensional Array in C using pointers.

Consider having a pointer int **x, which has been dynamically allocated and shows at some memory part, or simply a 2D array int[ROWS][COLS]. Then you can access any element by using *(*(x+i) + j) or x[i][j], where i are the rows and j are the columns.

However, note that a double pointer is not the same as a 2D array.

What does b evaluates to if b is a 2D array?

When b is a 2D array, b is also a pointer to the first element of the array. So it is the same as b[0], as well as b[0][0].

Marievi
  • 4,951
  • 1
  • 16
  • 33
  • 2
    Very Important -- **"However, note that a double pointer is not the same as a 2D array"** – David C. Rankin May 11 '17 at 06:14
  • @DavidC.Rankin true, I will highlight it. – Marievi May 11 '17 at 06:14
  • 1
    You highlighted, but it is not clear why you use this type for an answer about nD arrays. There is no need to use something like `int **` if you want to allocate a multidimensional array dynamically! That is a common error mad by people who not really unmderstand pointer and arrays (and the correct syntax). And "_When `b` is a 2D array, **`b` is also a pointer to the first element of the array**_" is plain wrong! An array is not a pointer, – too honest for this site May 11 '17 at 06:36
  • 1
    @Olaf he asked about accessing elements of a Multi-dimensional Array in C using pointers, so this is what I thought he wanted to see. Of course I know that there is no need to use something like `int **`, but this is what I thought that fitted better the question. – Marievi May 11 '17 at 06:38
  • 1
    @Marievi: He asks about "using pointer notation", not "using pointers". That's a significant difference. Nevertheless, both variants show a missconception about how arrays and pointers are related and how the index operator works (and which argument types it takes). – too honest for this site May 11 '17 at 06:42
  • 2
    @Olaf Question 3 is clear : How to access elements of a Multi-dimensional Array in C using pointers. Anyway, this is my opinion about what suits the question better. – Marievi May 11 '17 at 06:44
  • The dynamic allocation example is just adding confusion to an otherwise good answer. I'd delete that part entirely. – Lundin May 11 '17 at 07:04
  • 1
    I guess I should have said the pointer-to-pointer part is just confusing, as it actually has no relevance to 2D arrays at all. You cannot have an `int**` pointing at a 2D array. See [Correctly allocating multi-dimensional arrays](http://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). Anyway, I now posted an answer too, which shows the correct pointer types. – Lundin May 11 '17 at 08:02