2 Pointer arithmetic in 2D array

question created at Sat, Jun 1, 2019 12:00 AM

I am learning C++. So, please excuse me for this long question.

I have written the below program for arrays. I understand the base address of the array is returned and the name of the array points to that. So, in the case of a 1D array, I can understand that

arr + 1

returns the address of next item of the array i.e.

arr + 4bytes

However, in the case of a 2D array, it is a little different. What I understand from the below cout statements that in memory arr2D[0], arr2D[1]..arr2D[4] all will be allocated 20bytes one after another as there are 5 cols i.e. 5 * 4 bytes

arr2D & arr2D[0] points to the same base address as expected; lines 43 & 45

So, if I do

arr2D[0] + 5

I get the address of arr2D[1]; line 47. But, when I do

arr2D + 5

I get a memory address 100 bytes from the base address; line 50. I don't understand why. Could anyone explain to me this?

#include <iostream>

using namespace std;

int main() {

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

cout << "Printing arr" << endl;
for (int i = 0; i < 5; i++) {
    cout << *(arr + i) << " ";
}
cout << endl;

cout << "Base address of 'arr': " << (unsigned long) arr
     << " EQUALS " << "&arr: " << (unsigned long) &arr
     << endl;

cout << "Address of 2nd item i.e. i = 1 is: " << (unsigned long) (arr+1)
     << endl;

cout << "arr[1] = " << arr[1] << ", "
     << "1[arr] = " << 1[arr] << ", "
     << "*(arr + 1) = " << *(arr + 1)
     << endl << endl;


int arr2D[5][5] = {{1,2,3,4,5},
                   {3,4,5,6,7},
                   {5,6,7,8,9},
                   {7,8,9,10,11},
                   {9,10,11,12,13}};

cout << "Printing arr2D" << endl;
for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        cout << *(arr2D[i] + j) << " ";
    }
    cout << endl;
}
cout << endl;


cout << "Base address of arr2D = " << (unsigned long) arr2D << endl; // this is fine

cout << "Address of arr2D[0] = " << (unsigned long) &arr2D[0] << endl; // this is fine

cout << "Address of arr2D[1] = " << (unsigned long) arr2D[1] << " EQUALS "
     << (unsigned long)(arr2D[0] + 5) << endl; // this is fine

cout << "Address of arr2D[1] = " << (unsigned long) arr2D[1] << " NOT EQUALS "
     << (unsigned long)(arr2D + 5) << endl; // I do not understand this, as arr2D and arr2D[0] is same

cout << "Address of arr2D[1][0] = " << (unsigned long)&arr2D[1][0] << endl;

cout << "arr2D[1][0] = " << *((arr2D[0] + 5) + 0) << endl;
}
1
  1. A 2D array is an array of 1D arrays, so on access, the array is converted to a pointer to the first 1D array (which is a pointer to the 2D arrray's first element in a loose sense of the word). If you then derefernce that pointer, the address of the first element in the first array is returned. In both cases that pointer will have the same address but the pointers will be of very different types. In the first case it is a pointer to array of int [5] and in the second case a pointer to int. See C11 Standard - 6.3.2.1(p3)
    2019-06-01 04:44:22Z
  2. It works the same in C++, I just don't have the cross-reference to that standard handy (monthly boot of windows for updates ...)
    2019-06-01 04:48:33Z
  3. 2019-06-01 04:50:42Z
2 Answers 2
arr2D[0] and arr2D point to the same address, but they point to different types.

arr2D[0] is the first row of the 2D array, therefore it decays to a pointer to the first element of that row (a single int). Meanwhile, arr2D is a 2D array (an array of arrays), so it decays to a pointer to the first row (a 5 element array).

As you know, pointer arithmetic is scaled to the size of the objects being pointed to by a pointer. Since arr2D points to 5 element int arrays, each object being pointed to has a size of 4*5=20 bytes (assuming 32-bit ints) so increasing the pointer by 5 results in a difference of 20*5=100 bytes.

2
2019-06-01 05:08:52Z
  1. Mr. Xiang thanks for the explanation.
    2019-06-01 05:15:19Z

From cppreference:

When array-to-pointer decay is applied, a multidimensional array is converted to a pointer to its first element (e.g., a pointer to its first row or to its first plane): array-to-pointer decay is applied only once

So arr2D decayed into a pointer to an int array of size five, and the size of that is 20.

2
2019-06-01 04:54:27Z
  1. Mr. Alexander thanks for the explanation
    2019-06-01 05:16:17Z
source placed here