int s[4][2] = {
{1234, 56},
{1212, 33},
{1434, 80},
{1312, 78}
};
int (*p)[1];
s[0]
points to a location in memory. That memory location happens to be the starting point of int s[4][2]
. When you make the assignment p = s[0], p
and p+0
also point to s[0]. So when you print any one of these with a "%d" specifier, you will get the value stored at that location which happens to be `1234'. If you would like to verify the address is the same for all of these, use a format specifier "%p" instead of "%d".
EDIT to address OP comment question...
Here is an example using your own int **s:
First, C uses pointers. Only pointers. No arrays. The []
notation gives the appearance of arrays, but any variable that is created using the []
notation (eg. int s[4][2]
) is resolved into a simple pointer (eg. int **s
). Also, a pointer to a pointer is still just a pointer.
int a[8]={0};
(or int *a then malloced)
will look the same in memory as will:
int a[2][4];
( or in **a=0; then malloced)
The statment:
s[row][col] = 1;
creates the same object code as
*(*(s + row) + col) = 1;
It is also true that
s[row] == *(s + row)
Since s[row]
resolves to a pointer, then so does *(s + row)
It follows that s[0] == *(s + 0) == *s
If these three are equal, whatever value is held at this address will be displayed when printing it.
It follows that in your code: given that you have assigned p = s[0]; and s[0] == *s
*(*(p + 0)) == *(s[0] + 0) == *s[0] == **s
printf("%d\n", >>>fill in any one<<<); //will result in 1234
Note, in the following printf statements, your comment indicates addresses were printed. But because you used the unsigned int format specifier "%u",
Consider p == s[0]; which is a pointer to the first location of s. Note that either s[0][0] or **s would give you the value held at the first location of s, but s[0] is the _address_ of the first memory location of s. Therefore, since p is a pointer, pointing to the address at s[0], the following will give you the address of p, or s[0] (both same):
printf("%p\n", *p); // 1256433(address of s[0][0])
As for *p, p was created as int (*p)[1]; and pointer array of 1 element. an array is resolved into a pointer, so again, in the following you will get the address pointing to s[0]:
printf("%u\n", **p);
In summary, both p and *p are pointers. Both will result in giving address when printed.
Edit 2 Answer to your question: So my question is what is the difference between a simple pointer and a pointer to an array?
Look toward the bottom of this tutorial download a pdf. It may explain it better...
But in short, C Does not implement arrays in the same way other languages do. In C, an array of any data type always resolves into a pointer. int a[10];
is just really int *a;
, with memory set aside for space to hold 10 integers consecutively. In memory it would look like:
a[0] a[9] |0|0|0|0|0|0|0|0|0|0| (if all were initialized to zero)
Likewise you would be tempted to think of float b[2][2][2];
as a 3 dimensional array: 2x2x2, it is not. It is really a place in memory, starting at b[0]
that has room for 8 floating point numbers. Look at the illustrations HERE.
This is the way arrays work in C -- arrays are not first class types, in that you can't do anything with them other than declaring them and getting their size. In any other context, when you use an expression with type array (of anything) it is silently converted into a pointer to the array's first element. This is often referred to as an array "decaying" into a pointer.
So lets look at your statements one by one:
p = s[0];
Here, s
has array type (it's an int[4][2]
-- a 2D int array), so its silently converted into a pointer to its first element (an int (*)[2]
, pointing at the word containing 1234
). You then index this with [0]
which adds 0 * sizeof(int [2])
bytes to the pointer, and then dereferences it, giving you an int [2]
(1D array of 2 ints). Since this is an array, its silently converted into a pointer to its first element (an int *
pointing at 1234
). Note that this is the same pointer as before the index, just the pointed at type is different.
You then assign this int *
to p
, which was declared as int (*)[1]
. Since C allows assigning any pointer to any other pointer (even if the pointed at types are different), this works, but any reasonable compiler will give you a type mismatch warning.
p
now points at the word containing 1234
(the same place the pointer you get from s
points at)
printf("%d\n", *(*(p+0)));
This first adds 0*sizeof(int[1])
to p and dereferences it, giving an array (int[1]) that immediately decays to a pointer to its first element (an int *
still pointing at the same place). THAT pointer is then dereferenced, giving the int value 1234
which is printed.
printf("%d\n", *(s[0]+0));
We have s[0]
again which via the multiple decay and dereference process noted in the description of the first line, becomes an int *
pointing at 1234
. We add 0*sizeof(int)
to it, and then dereference, giving the integer 1234
.
printf("%u\n", p);
p
is a pointer, so the address of the pointer is simply printed.
printf("%u\n",*p)
p
is dereferenced, giving an int [1]
(1D integer array) which decays into a pointer to its first element. That pointer is then printed.