I know that for single-dimensional arrays x=a[i]
is equivalent to x=*(a+i)
, but how can I access elements of a two-dimensional arrays using pointers?

- 1,805
- 4
- 29
- 47
-
1Do you understand how a multi-dimensional array is laid out in memory? Can you access `a[0][0]`? `a[0][1]`? `a[0][ARY_N_Y]`? `a[1][0]`? – dmckee --- ex-moderator kitten Nov 25 '12 at 18:53
-
2C doesn't actually have two-dimensional arrays. – Russell Borogove Nov 25 '12 at 18:54
-
7@RussellBorogove That kind of statement is dependant on the claim that *"an array of arrays isn't the same as a two-dimensional array"* which always comes down to some pendants claim about what it means for an block of memory to be a two dimensional array. In any case, `int a[5][5];` looks and acts like a 2d array. At least until it decays to a pointer. – dmckee --- ex-moderator kitten Nov 25 '12 at 19:01
-
6It's "pedants", not "pendants". – Russell Borogove Nov 25 '12 at 23:15
-
2There should be an accent aigu on the e: *touché*. On the Mac you get that character with Alt-E (aka option-E), E. – Russell Borogove Nov 27 '12 at 02:20
6 Answers
Summary: If you have a multidimensional array defined as int [][]
, then x = y[a][b]
is equivalent to x = *((int *)y + a * NUMBER_OF_COLUMNS + b);
Boring Details:
The (int *)
cast of y
above deserves some explanation, as its necessity may not be at-first intuitive. To understand why it must be there consider the following:
Typed pointer arithmetic in C/C++ always adjusts the typed pointer value (which is an address) by the size of the type in bytes when adding/subtracting/incrementing/decrementing by scalar.
The fundamental type of a multi-dimensional array declaration (not the element type; the variable type) is an array-type of one-less dimension than the final dimension.
The latter (#2) of these really needs an example to solidify. In the following, variables ar1
and ar2
are equivalent declarations.
int ar1[5][5]; // an array of 5 rows of 5 ints.
typedef int Int5Array[5]; // type is an array of 5 ints
Int5Array ar2[5]; // an array of 5 Int5Arrays.
Now the pointer arithmetic part. Just as a typed structure pointer can be advanced by the size of the structure in bytes, so can a full dimension of an array be hopped over. This is easier to understand if you think of the multi-dimensioned array as I declared ar2 above:
int (*arptr)[5] = ar1; // first row, address of ar1[0][0].
++arptr; // second row, address of ar[1][0].
All of this goes away with a bare pointer:
int *ptr = ar1; // first row, address of ar1[0][0].
++ptr; // first row, address of ar1[0][1].
Therefore, when doing the pointer arithmetic for two-dimensional array, the following would NOT work in getting the element at [2][2]
of a multi-dimensioned array:
#define NUMBER_OF_COLUMNS 5
int y[5][NUMBER_OF_COLUMNS];
int x = *(y + 2 * NUMBER_OF_COLUMNS + 2); // WRONG
The reason is hopefully obvious when you remember that y
is an array of arrays (declaratively speaking). The pointer arithmetic of adding the scaler (2*5 + 2)
to y
will add 12 rows, thereby computing and address equivalent to &(y[12])
, which is clearly not right, and in fact, will either throw a fat warning at compile time or outright fail to compile altogether. This is avoided with the cast of (int*)y
and the resulting type of the expression being based on an bare pointer-to-int:
#define NUMBER_OF_COLUMNS 5
int y[5][NUMBER_OF_COLUMNS];
int x = *((int *)y + 2 * NUMBER_OF_COLUMNS + 2); // Right!

- 5,702
- 2
- 26
- 33
-
@WhozCraig Then it would be ROW_SIZE, wouldn't it? Changed it anyway. – antonijn Nov 25 '12 at 18:57
-
I tried testing this by printing one element of a two-dimensional array like this printf("%d",*(a + 2 * 3 + 3));. It should've printed the element a[2][3] of a matrix with the row width of 3. In my case the element a[2][3] is 6, but 0 gets printed. Am I doing something wrong? – Tudor Ciotlos Nov 25 '12 at 19:15
-
@TudorCiotlos "Am I doing something wrong?" how should I know? You didn't provide the source (do that in another question btw). – antonijn Nov 25 '12 at 19:21
-
@TudorCiotlos Probably not, the pointer arithmetic here is not right. The correct arithmetic is in [the other answer](http://stackoverflow.com/a/13554368/1011995), just disregard the last sentence there, a 2D-array is very different from an `int**`. – Daniel Fischer Nov 25 '12 at 19:24
-
this is incorrect. `y+1` hops over the entire first row already. – Johannes Schaub - litb Nov 25 '12 at 19:24
-
-
@JohannesSchaub-litb No it doesn't, just compiled it and it gave me the desired results. – antonijn Nov 25 '12 at 19:36
-
@JohannesSchaub-litb How? At least take the time to correct my mistakes. – antonijn Nov 25 '12 at 19:47
-
since you have been rejecting my corrections, i have given up doing that. – Johannes Schaub - litb Nov 25 '12 at 19:49
-
let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/20078/discussion-between-antonie-blom-and-johannes-schaub-litb) – antonijn Nov 25 '12 at 19:52
-
Thanks for the answer (+1). But it's hard to understand since you always use the same size for both dimensions. Using different sizes would make it clearer whether columns or rows are resolved first... – DaveFar Jan 27 '15 at 16:19
The table
In C 2D arrays are continuous series of lines (not like in Pascal).
When we crate a table of integers with 4 rows and 5 columns:
Reaching the elements
We can reach the elemnts with:
int element = table[row-1][column-1];
But we can also do this with the following code:
int element = *(*(table+row-1)+column-1);
In these examples row
and column
is counted from 1, thats the reason for the -1.
In the following code you can test that both technique is correct. In this case we count the rows and columns from 0.
Example
#include <stdio.h>
#include <stdlib.h>
#define HEIGHT 4
#define WIDTH 5
int main()
{
int table[HEIGHT][WIDTH] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
int row = 2;
int column = 2;
int a = *(*(table+row)+column);
printf("%d\n",a);//13
printf("%d\n",table[row][column]);//13
return 0;
}
Explanation
This is a double poiner arithmetic, so table
points to the first row and *table
points to the first element, if you derefer it than **table
will return the value of the first element. In the following example you can see that *table
and table
is pointing to the same memory address.
printf("%d\n",table);//2293476
printf("%d\n",*table);//2293476
printf("%d\n",**table);//1
In the memory all the rows of the table are following eachother. Because table
pointing to the first row if we add the row number where the needed element is in the table, we will get a pointer that points to that row. In this case *(table+row)
will contain an address to the first element of the given row. Now we just have to add the column number like *(table+row)+column
, and we get the adress of the element in the given row and column. If we derefer this, we get the exact value of this element.
So if we count the rows and columns from zero, we can get elements fromt the table like this:
int element = *(*(table+row)+column);
In the memory

- 29,531
- 22
- 131
- 165
-
i like your graphics, but you must mention that table is to be treated like a char pointer and you still must add the sizeof of the elements. if it remains with the type of the 2d array, you are hopping over an entire row by adding 1 – Johannes Schaub - litb Nov 25 '12 at 19:44
-
That's not correct for an `int table[rows][cols];`. In `(table + integer_expression)`, `table` is converted to an `int (*)[cols]`. – Daniel Fischer Nov 25 '12 at 19:44
A 2D array is viewed as an array of 1D arrays. That is, each row in a 2D array is a 1D array. Therefore given a 2D array A
,
int A[m][n].
In general,
A[i][j] = *(A[i]+j)
also
A[i] = *(A+i)
so,
A[i][j] = *(A[i]+j) = * ( *(A+i)+j).

- 573
- 1
- 6
- 15
-
2Sooo close to an upvote, but the last sentence is too incorrect to upvote as is. 2D arrays (`int arr[rows][cols];`) are not to be confused with double pointers (`int **pp;`). If you remove that, I'll be very happy to upvote. – Daniel Fischer Nov 25 '12 at 19:26
The previous answers already explained very well, I would just list pointer expressions according to my understanding, and compare them with the arr[i][j] format.
Pointer expression of 2-D array: the array name itself is a pointer to first sub array, arr: will be pointer to first sub array, not the first element of first sub array, according to relationship of array & pointer, it also represent the array itself, arr+1: will be pointer to second sub array, not the second element of first sub array, *(arr+1): will be pointer to first element of second sub array, according to relationship of array & pointer, it also represent second sub array, same as arr[1], *(arr+1)+2: will be pointer to third element of second sub array, *(*(arr+1)+2): will get value of third element of second sub array, same as arr[1][2],
Similar to 2-D array, multiple-D array has similar expression.

- 22,183
- 20
- 145
- 196
A practical way to access with a pointer.
typedef struct
{
int Array[13][2];
} t2DArray;
t2DArray TwoDArray =
{
{ {12,5},{4,8},{3,6},{7,9},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{4,0},{5,0},{5,1} }
};
t2DArray *GetArray;
int main()
{
GetArray = &TwoDArray;
printf("\n %d\n %d\n %d\n %d\n %d\n %d\n",
GetArray->Array[0][0],
GetArray->Array[0][1],
GetArray->Array[1][0],
GetArray->Array[1][1],
GetArray->Array[2][0],
GetArray->Array[2][1]);
getchar();
return 0;
}
OUT
12 5 4 8 3 6

- 21
- 1
#include <iostream>
using namespace std;
int main()
{
//FOR 1-D ARRAY THROUGH ARRAY
int brr[5]= {1,2,3,4,5};
for(int i=0; i<5; i++)
{
cout<<"address ["<<i<<"] = " <<&brr[i]<<" and value = "<<brr[i]<<endl;
}
//FOR 1-D ARRAY THROUGH POINTER
cout<<endl; // endl TO MAKE OUT PUT LOOK CLEAR AND COOL :)
int (*q)=brr;
for(int i=0; i<5; i++)
{
cout<<"address ["<<i<<"] = " <<&brr[i]<<" and value = "<<*(q+i)<<endl; //(p[i][j])
}
cout<<endl;
//FOR 2-D ARRAY THROUGH ARRAY
int arr[2][3] = {1,2,3,4,5,6};
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
cout<<"address ["<<i<<"]["<<j<<"] = " <<&arr[i][j]<<" and value = "<<arr[i][j]<<endl;
}
}
//FOR 2-D ARRAY THROUGH POINTER
int (*p)[3]=arr; // j value we give
cout<<endl;
for(int i=0; i<2; i++)
{
for(int j=0; j<3; j++)
{
cout<<"address ["<<i<<"]["<<j<<"] = " <<(*(p+i)+j)<<" and value = "<<(*(*(p+i)+j))<<endl; //(p[i][j])
}
}
return 0;
}
==============OUT PUT======================
//FOR 1-D ARRAY THROUGH ARRAY
address [0] = 0x28fed4 and value = 1
address [1] = 0x28fed8 and value = 2
address [2] = 0x28fedc and value = 3
address [3] = 0x28fee0 and value = 4
address [4] = 0x28fee4 and value = 5
//FOR 1-D ARRAY THROUGH POINTER
address [0] = 0x28fed4 and value = 1
address [1] = 0x28fed8 and value = 2
address [2] = 0x28fedc and value = 3
address [3] = 0x28fee0 and value = 4
address [4] = 0x28fee4 and value = 5
//FOR 2-D ARRAY THROUGH ARRAY
address [0][0] = 0x28fee8 and value = 1
address [0][1] = 0x28feec and value = 2
address [0][2] = 0x28fef0 and value = 3
address [1][0] = 0x28fef4 and value = 4
address [1][1] = 0x28fef8 and value = 5
address [1][2] = 0x28fefc and value = 6
//FOR 2-D ARRAY THROUGH POINTER
address [0][0] = 0x28fee8 and value = 1
address [0][1] = 0x28feec and value = 2
address [0][2] = 0x28fef0 and value = 3
address [1][0] = 0x28fef4 and value = 4
address [1][1] = 0x28fef8 and value = 5
address [1][2] = 0x28fefc and value = 6

- 9
- 4