I have an example involving a pointer to a 2D array. Can someone help me understand what is going on in this example?
int main()
{
int i = 0, j=0, sum0
data
is an array of 3-element arrays of integers. In contexts that expect a "pointer to foo", you can use an "array of foo" and it will behave like a pointer to its first element, so *data
is a pointer to the first element of data
, namely (so to speak) {23,55,50}
.
So, the answer to the first question in the comments: No, it isn't true that Ptr = 23
. (It couldn't be; Ptr
is an int *
and 23 is an int
.)
You are correct that Ptr = *(data+i)
makes Ptr
point to the i
th row of data
. More precisely, data
is an array of 3-element arrays of int, which behaves like a pointer to 3-element arrays of int; adding i
to it moves past i
such arrays.
The usual way to access other columns of the array is ordinary array indexing. If you refer to data[i][j]
, you're getting column j
of row i
. If you want to do it with explicit pointer arithmetic, then note that (e.g.) Ptr
in the example code is of type "pointer to integer", so Ptr+1
(for instance) is element 1 of whatever row Ptr
is pointing to. (But, as a matter of style, you should generally not do explicit pointer arithmetic when you don't actually need to.)
Ptr = *data;
is short for *(data+0)+0
which is a pointer for first column element of the first row. the first 0 added with data is the row no., which is indirected and takes us to the first row. * (data+0)
is still a address and not a value it points to (for 2D array). So, Ptr now points to the address of first column in first row. The second zero is the column no.. So, first row and first column's memory address is chosen. Using indirection (*) again would only now give value that the address holds. like * (*(data+0)+0)
or **data
.
Generally, if p is pointer name,i row number and j column number,
(*(p+i)+j)
would give a memory address of a element in 2D array. i is row no. and j is col no.,*(*(p+i)+j)
would give the value of that element.*(p+i)
would access the ith row*(p+i)
. You may have to declare the pointer as (*p)[columns]
instead of just *p
. Doing so, you are declaring pointer to an 2D array.Using pointer arithmetic is treating 2d array like 1D array. Initialize pointer *Ptr to first element (int *Ptr = *data
) and then add an no. (Ptr + n
) to access the columns. Adding a number higher than column number would simply continue counting the elements from first column of next row, if that exists.
In your example the loop goes through all matrix rows to find the one whose sum of all elements holds the maximum value.
At the beginning a pointer to the first row is assigned:
Ptr = *data;
Which means that the following is true:
(Ptr[0] == 23 && Ptr[1] == 55 && Ptr[2] == 50)
Notice that Ptr is a pointer so it holds a memory address, hence Ptr is different than 23 (unless the memory address happens to be 23, which is unlikely to happen).
data
is a 2 dimentional array, which has 4 rows and each row has 3 elements (ie 4 X 3).
Now, Ptr = *data;
means you are storing the starting address of 1st row to the pointer variable Ptr
. This statement is equivalent to Ptr = *(data + 0)
. Ptr = *(data + 1)
- this means we are assigning 2nd row's starting address.
Then *Ptr
or *(Ptr + 0)
will give you the value of the first element of the row to which is pointing. Similarly, *(Ptr + 1)
will give you the value of the second element of the row.
The for
loop in your program is used to identify which row has the maximum value of the sum of its elements (3 elements). Once the control comes out of that for
loop, Ptr
will be pointing to the row which has the maximum sum of its elements and sum0
will have the value of the sum.
Consider an array int a[5];
, I hope you know that a[0]
and 0[a]
is the same. This is because a[0]
means *(a+0)
and 0[a]
means *(0 + a)
. This same logic can be used in 2 dimensional array.
data[i][j]
is similar to *(*(data + i) + j)
. We can write it as i[data][j]
also.
For more details please refer to the book "Understanding Pointers in C" by Yashavant Kanetkar.
C allows multidimensional arrays, lays them out in memory as contiguous locations, and does more behind the scenes address arithmetic. Consider a 2-dimensional array.
int arr[ 3 ][ 3 ] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
The compiler treats a 2 dimensional array as an array of arrays. where an array name is a pointer to the first element within the array. So, arr points to the first 3-element array, which is actually the first row (i.e., row 0) of the two-dimensional array. Similarly, (arr + 1) points to the second 3-element array (i.e., row 1) and so on. The value of this pointer, (arr + 1), refers to the entire row. Since row 1 is a one-dimensional array, (arr + 1) is actually a pointer to the first element in row 1. Now add 2 to this pointer. Hence, ((arr + 1) + 2) is a pointer to element 2 (i.e., the third element) in row 1. The value of this pointer, ((arr + 1) + 2), refers to the element in column 2 of row 1.