1

I know that if arr is an array then arr[i]=*(arr+i); and if is a 2D array then arr[i][j]=*(*(arr+i)+j); So I have this code

main(){
    int arr[5][5];
    int arr2[25];   // same as arr[5][5];
    int i,j;


    for(i=0;i<5;i++)
        for(j=0;j<5;j++){
            arr[i][j]=i+j;
            printf("arr[%d][%d] is at %p\n",i,j,&arr[i][j]);
        }

    printf("*(arr+i)=%d\n",*(arr+1)); // why this dont work


    for(i=0;i<24;i++){
       arr2[i]=i;
       printf("arr2[%d] is at %p\n",i,(arr2+i));
    }

    printf("*(arr+i)=%d\n",*(arr2+1)); // prints 1 as expected
}

I know that in C there's no such thing as 2D array, its basically a linear row major contiguous blob of memory. So I'm wondering why I cant print the value of 2D arr using *(arr+1), which means add 1*5*4 bytes to the base of arr and dereference the value at that address. I know that **(arr+1) works but I dont know why I need that extra asterix ? Also If I do this printf("*(arr+i)=%p\n",*(arr+1)); is the same as I would use (arr+i) to interpret as an address

lychee
  • 1,771
  • 3
  • 21
  • 31

3 Answers3

3

arr is an array of arrays of ints. Its type is int [5][5]. So, the elements of arr is 1D arrays. When used in expression, in most cases, arrays converted to a pointer to its first element. In *(arr + 1), arr is converted to pointer to arr[0], i.e, first 1D array. Adding 1 will increment it by 5*4 = 20 bytes, i.e, next element of array arr which is arr[1].

Since arr[1] is an array, it can't be printed (as a whole), but its address can be. arr[1] is itself an array and it will decay to pointer to its first element, i.e, arr[1][0]. To print its element you need another dereference which is acheived by arr[1][j] (j is columns).

arr[1][j] is equivalent to *(arr[1] + j) which is ultimately equivalent to *(*(arr + 1) + j).

Suggested Reading: What exactly is the array name in c?

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
  • So basically `arr[5][5]` is same as `arr[25]` just when used in expressions `arr[0]`,`arr[1]`,`arr[2]`,`arr[3]` and `arr[4]` will have `int*` type? – lychee Mar 12 '15 at 19:57
  • @BsD; You can say. But, sometimes memory management differs in 1D and 2D array containing equal number of elements. – haccks Mar 12 '15 at 19:59
2

The type of *(arr+1) = the type of arr[1] = int [5], which will decay to int* when used in printf.

To print the pointer, use:

printf("*(arr+i)=%p\n", *(arr+1));

To print the object it points to, use:

printf("*(*(arr+i))=%d\n", *(*(arr+1)));

You can make your code easier to read by using:

printf("arr[1] = %p\n", arr[1]);       // Print the pointer
printf("arr[1][0] = %d\n", arr[1][0]); // Print the value
R Sahu
  • 204,454
  • 14
  • 159
  • 270
2

As you said, a 2D array in C is basically an array of 1D arrays. You might think of this as an array of rows.

The rightmost * will dereference the outer array, selecting the row you want.

*(arr+i)      //this gives me a pointer to the row I want

The * to the left of that will dereference in the inner array, selecting an element from the row.

*(*(arr+i)+j) //this gives me an element in the row

**(arr+i) is just a special case of the above where the column number j is 0.

eigenchris
  • 5,791
  • 2
  • 21
  • 30