elyashiv
elyashiv

Reputation: 3691

why does this pointer arithmetic on a 2D array work?

I wrote the following code:

#include <iostream>
using namespace std;

int main()
{
    int a[10][10];
    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            a[i][j] = i * j;
    cout << *(*(a + 3) + 4) << endl;
    return 0;
}

I was expecting it to print some garbage data, or a segmentation fault. What I got was 12. I tested it both in c and c++ (using gcc and g++ respectively), and I herd this works the same on VS although I haven't tested this. Why does this work, and is there a official documentation of this behavior?

Upvotes: 2

Views: 2153

Answers (6)

Ravi
Ravi

Reputation: 1

The output you got is 12 and it is absolutely correct. You did a[i][j] = i*j ; for each element of the array. Now you print *( *(a + 3) + 4) which is the same as a[3][4]. As you did a[i][j] = i*j, you now have a[3][4] = 3*4 = 12. So it will print 12.

Upvotes: -2

SHR
SHR

Reputation: 8333

When you want a simple answer build the complex type with typedefs

it means:

int a[10][10];

will be:

typedef int a10[10]; //a10 is array of 10 ints 
a10 a[10]; //a is array of 10 a10s

now to understand the sizes and position:

sizeof(a) = 10 * 10 * sizeof int
sizeof(a[0]) = is  10 * sizeof int
a+1 is equal to &a[1]

When you increment a pointer by 3 it is mean increment by sizeof of the type.

address of a[1] == address of a[0] + sizeof(a[0])

Therefore:

*(*(a + 3) + 4) == a[3][4] 

Upvotes: 1

user1508519
user1508519

Reputation:

See this question for a detailed explanation.

Two dimensional arrays ([][], not **) are contiguous in memory, as a result you can access elements using the following formula:

*((int *)array + X * NUMBER_OF_COLUMNS + Y);

i.e.

std::cout << *((int *)a + 3 * 10 + 4);

Upvotes: 2

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145457

The declaration

int a[m][n];

means an array of m arrays, where each such inner array is of size n.

I remember that by remembering that the last index varies fastest.

In the expression (a + 3) the a reference to the outer array decays to pointer to item of that outer array. I.e. pointer to size n array. The + 3 then adds 3 times the byte size of the inner array, to the address of the a-as-pointer.

Dereferencing this gets you a pointer to int.

Adding 4 to that gets you 4 positions into the inner array.

The beauty of this scheme is that it also works with "jagged arrays", arrays of pointers, because there the types are different.

The very sad thing about it is that it doesn't work well with C++ derived classes, because an array of Derived decays to pointer to Derived which then can be implicitly converted to pointer to Base, which when indexed yields formal Undefined Behavior (the size of Derived can be greater than the size of Base).

Upvotes: 4

isick
isick

Reputation: 1487

You can index an array using *(arr + index) or arr[index]. They are semantically different, but functionally the same.

See this Stack Overflow discussion for more.

Difference Between *(Pointer + Index) and Pointer[]

Upvotes: 1

slecorne
slecorne

Reputation: 1718

*(a + b)=a[b] you take the address of a, move it by b and take the value at the corresponding address

So *(*(a + 3) + 4)means *(a[3]+4) which mean a[3][4]=12

Upvotes: 8

Related Questions