In your code snippet
#include <stdio.h>
int main() {
int a[2][2] = { 0,1,2,3};
printf("\n%d %d \n%d %d\n",a[0][0],a[0][1],a[1][0],a[1][1]);
printf("%d %d %d %d\n",*a[0],*a[1],*a[2],*a[3]);
return 0;
}
the line
printf("%d %d %d %d\n",*a[0],*a[1],*a[2],*a[3]);
is equivalent to:
printf("%d %d %d %d\n",a[0][0],a[1][0],a[2][0],a[3][0]);
This means that you are accessing the object a
out of bounds, which invokes undefined behavior.
What you probably want to do is the following:
#include <stdio.h>
int main() {
int a[2][2] = { {0,1}, {2,3} };
int *p = &a[0][0];
printf("%d %d \n%d %d\n",a[0][0], a[0][1], a[1][0],a[1][1]);
printf("%d %d %d %d\n", p[0],p[1], p[2], p[3] );
return 0;
}
Another way of writing this is like this:
#include <stdio.h>
int main() {
int a[2][2] = { {0,1}, {2,3} };
printf( "%d %d \n%d %d\n", a[0][0], a[0][1], a[1][0], a[1][1] );
printf( "%d %d %d %d\n", a[0][0], a[0][1],a[0][2], a[0][3] );
return 0;
}
These programs have the following output on my compiler:
0 1
2 3
0 1 2 3
Although this will probably work on all compilers, it is worth noting that doing this may invoke undefined behavior, depending on how strictly you interpret the standard. This is because you are accessing the first sub-array a[0]
out of bounds, but not the object a
as a whole. See the following question for further information:
One-dimensional access to a multidimensional array: is it well-defined behaviour?
The compilers gcc and clang actually both provide a run-time warning for the second program, if I compile with -fsanitize=undefined
. The compiler clang additionally provides a compile-time warning, if I enable all warnings.
For these reasons, it would probably be better to declare a 1D array instead of a 2D array, and to perform the index calculatings into the 1D array yourself, if you want to use the 1D array as a 2D array. That way, you can be sure that what you are doing is allowed by the ISO C standard. Here is an example:
#include <stdio.h>
#define ROWS 2
#define COLUMNS_PER_ROW 2
int calculate_1D_offset( int row, int column )
{
return row * COLUMNS_PER_ROW + column;
}
int main( void )
{
int a[ROWS*COLUMNS_PER_ROW] = { 0, 1, 2, 3 };
//find the value of a[1][0], as if "a" were a 2D array
printf( "%d\n", a[calculate_1D_offset(1,0)] );
}
This program has the following output:
2
so why are the memory addresses of the first two elements &a[0][0] = a[0] and &a[0][1] = a[1] but the last two don't match?
The array a
consists of 2 sub-arrays, each consisting of 2 int
elements. So the total number of int
elements is 4.
In your question, the addresses are the following:
1137924528
is the address of the element a[0][0]
.
1137924532
is the address of the element a[0][1]
.
1137924536
is the address of the element a[1][0]
.
1137924540
is the address of the element a[1][1]
.
In your question, the line
printf("%d %d %d %d\n",a[0],a[1],a[2],a[3]);
has the following output:
1137924528 1137924536 1137924544 1137924552
The last two addresses are out of bounds, because the sub-arrays a[2]
and a[3]
do not exist. Only a[0]
and a[1]
exist.
If a[2]
did exist, its address would be 1137924544
, which would be the the address of the 5th int
element of the 2D array, i.e. a[0][4]
(because indexes in C are 0-based).
However, I doubt that these addresses are actually correct, because you are using the wrong printf
format specifier for printing an address. In order to print an address, you should use %p
instead of %d
, as %d
is intended for an int
, not a pointer. On platforms on which pointers are 64-bit and an int
is 32-bit, the 32 most significant bits may be stripped off the value, or worse.