Question 1
My question is, how come this doesn't work for a two-dimensional array?
Answer
for (k=0; k<=g_count-1; k++)
sum += *(g+k);
is wrong on two counts.
*(g+k)
does not evaluate to an int
.
*(g+k)
accesses the array out of bounds when k > 1
.
When g
is declared as:
int g[2][4];
g
decays to a pointer of type int (*)[4]
. It does not decay to a pointer of type int*
.
What type does g+k
evaluate to? It also evaluates to a pointer of type int (*)[4]
.
Where does it point to? It will be helpful to see that with a diagram.
|<--- memory used by g -->|
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
address of g
|
v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
address of g[0] address of g[1]
| |
v v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
When used in an expression, g
decays to the address of g[0]
.
The expression g
evaluates to the address of g[0]
.
The expression g+1
evaluates to the address of g[1]
.
g g+1 g+2
| | |
v v v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
As you can see, g+k
points to a location beyond the valid limits when k > 1
. Derefercencing g+k
will lead to undefined behavior when k > 1
.
You could use:
int* ptr = &g[0][0]; // Pointer to the first int in the 2D array.
for (k=0; k<=g_count-1; k++)
sum += *(ptr+k);
// ^^^ ptr, not g
That will be valid use of the array and the pointers.
Question 2
I've noticed that while &g[0][0]
and g
hold the same value, &g[0][0]+1
and g+1
do not. Can someone please explain why?
Answer
Given the array, we have:
g g+1
| |
v v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
&g[0][0]
| &g[0][0]+1
| |
v v
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
From the diagram, you can see why expressions g
and &g[0][0]
evaluate to the same address. However, the type of the expressions are not the same. The expression g
evaluates to int (*)[4]
while &g[0][0]
evaluates to int*
.
Since the type of the expression g
is int (*)[4]
, the offset between g
and g+1
is the same as the size of 4 int
s.
Since the type of the expression &g[0][0]
is int*
, the offset between &g[0][0]
and &g[0][0]+1
is the same as the size of one int
.
That explains why g+1
does not evaluate to the same address as &g[0][0]+1
even though g
and &g[0][0]
evaluate to the same address.