Reputation: 6250
I'm working through toy problems to understand the differences between pointers and arrays in C and I've stumbled upon something I'm not yet able to grok or find an answer to.
I have the following program
#include <stdio.h>
int main()
{
int a[3][3] = {{1, 2, 3}, {4, 5,6}, {7, 8, 9}};
int (*b)[3];
b = a;
printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]);
printf("%d %d %d\n", *b[0], *b[1], *b[2]);
b++;
printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]);
b++;
printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]);
return 0;
}
And when I compile and run it I get this:
me@mac: clang -g q.c -o q.o
me@mac: ./q.o
1 2 3
1 4 7
4 5 6
7 8 9
My question is what's the difference between (*b)[0]
and *b[0]
? It appears that the former is of type int *
while the latter is of type int *[3]
. How to interpret the operators *[]()
to grok this?
Upvotes: 4
Views: 133
Reputation: 28830
A bit late to the party, but answers seem to miss some important points.
what is the difference between (*b)[0] and *b[0]?
provided that b is a pointer arrays of 3 int, and points to a.
int (*b)[3] = a; // int a[3][3]
to avoid some confusion, let say that a and b are
int a[X][Y]; // in your example, X=Y=3
int (*b)[Y] = a; // this line probably gives some clue about what b is
This is a matter of precedence. []
takes precedence over *
, meaning that
if you don't put the parents to *b[0]
, b[0]
is evaluated first and yields a int [Y]
, the first [Y]
array of [X][Y]
, then *
is applied and decays (dereferences) into an int
, the first int of that array of Y
.
Result (or target) is the int in a[0][0]
.
with the parents, (*b)[0]
, *b
is evaluated first yielding a int [Y]
, the first one, then the [0]
gives the first int of that [Y]
.
Result (or target) is the int in a[0][0]
. Again... really?
But the two [0]
are not the same thing! The confusion comes from both the *
and [0]
yield to the first element, however the order of evaluation is different in both cases.
Upvotes: 0
Reputation: 106012
b
is a pointer to an array of 3
int
s. In the assignment
b = a;
a
will decay to pointer to its first element. Since a
is an array of arrays, its first element is and array of 3
int
s. Therefore, the above statement is equivalent to
b = &a[0];
So, b
is pointing to array a[0]
. The elements of array a[0]
can be accessed by using index a[0][i]
. In pointer arithmetic equivalent it is *(*(a + 0) + i)
= *(*(a) + i)
= *(*a + i)
= (*a)[i]
.
In the expression (*a)[i]
the type of a
after conversion is int (*)[3]
which is also the type of b
. Therefore, array a[0]
can also be accessed by using (*b)[i]
.
So, the statement
printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]);
is equivalent to
printf("%d %d %d\n", (*a)[0], (*a)[1], (*a)[2]);
or
printf("%d %d %d\n", a[0][0], a[0][1], a[0][2]);
Now look at *b[0]
. As per operator precedence rule, *b[0]
is equivalent to *(b[0])
. Simply b[0]
is representing array a[0]
as discussed above and array converted to pointer to its first element when used in an expression, with some exception there, b[0]
is actually a pointer to element a[0][0]
in the expression *(b[0])
. *
out of ()
dereferencing this pointer and giving the value present at &a[0][0]
. Similarly, *b[1]
and *b[2]
are giving the elements at the address &a[1][0]
and &a[2][0]
.
Therefore, the statement
printf("%d %d %d\n", *b[0], *b[1], *b[2]);
is equivalent to
printf("%d %d %d\n", *a[0], *a[1], *a[2]);
or
printf("%d %d %d\n", &a[0][0], &a[0][1], &[0][2]);
This results in a conclusion that both (*b)[0]
and *b[0]
are of same type, int
.
Upvotes: 0
Reputation: 1901
My question is what is the difference between (*b)[0] and *b[0]?
int (*b)[3] ;
is pointer to one dimensional array of size 3 In this case it first dereference the pointer and then do index access because of ()
.
*b[3]
is array of 3 pointers, In this case first do index access because of [ ];
because of that when you doing
printf("%d %d %d\n", (*b)[0], (*b)[1], (*b)[2]);
printf("%d %d %d\n", *b[0], *b[1], *b[2]);
in first printf
it is printing element of first one dimensional array in second printf
it is pointing to first element of each row.
after b++
in first case pointing to second array and second printf
it is pointing to second element of each row.
Upvotes: 1
Reputation: 31153
This only applies to two-dimensional arrays, not to any random pointers.
When using (*b)[1]
the dereferencing is done first and then the indexing, so it actually means b[0][1]
and you are getting values from the first array.
If you use *b[1]
it is the same as *(b[1])
. The indexing operator will be handled first and the the dereferencing, so you get b[1][0]
.
Upvotes: 2
Reputation: 213799
int (*b)[3];
is an array pointer, a special kind of pointer that can point to a whole array and not just to the first element. Not to be confused with int *b[3]
which is an array of 3 pointers and not present in your code.
b=a
sets b to point to the first element in the 2D array a
, which is a 1D array.
When you dereference an array pointer, you get the array. And when an array is used in an expression, it "decays" into a pointer to the first element, which explains the first printf line.
If you write *b[0]
, then [] has higher operator precedence than *, so it means "give me array number 0, it will decay into a pointer to the first element, give me the contents of that element".
For any pointer type, array pointers included, pointer increments of b
follow the rules of pointer arithmetic: increase the address so that the pointer points at the next adjacent item of pointed-at-type in memory. That is, increase the address with sizeof(*b)
bytes, which will be 3*sizeof(int)
in this example.
Upvotes: 3
Reputation: 75062
(*b)[0]
first dereference the pointer and then do index access. It is equivalent to *((*b)+(0))
.
*b[0]
first do index access and then dereference the pointer. It is equivalent to **((b)+(0))
.
Adding zero means virtually nothing, so both of them are equivalent to **b
with type int
, so there are virtually no difference.
Upvotes: 0