the pointer of the entire array - arrays

int main(){
int a[][3]={1,2,3,4,5,6};
int (*ptr)[3]=a;
printf(" %d",(*ptr)[1]) ;
}
I know that the variable ptr is a pointer of the first 1d array of type int, in other words the variable ptr will store the the address of the first 3 integers, first let's suppose that the base address of a is 1000 so as I think this 2d array will be stored in the memory in this form:
elements: | 1 | 2 | 3 || 4 | 5 | 6 |
addressed of each element: | 1000 | 1004 | 1008 || 1012 | 1016 | 1020 |
---------------------------------||---------------------------------
addressed of each array: 1000 1012
So ptr will store the value 1000 which is the address of the first array. And that means *ptr or (*ptr)[0] will give me the address of the first element, and *ptr+1 or ((*ptr)[1]) will give me the address of the second element and so on.
So as I understand *ptr[1] will give the address of the second element, and not it's value.
But from the output it seem that I am wrong. So I want to know what is the problem in my process.

You are correct until this part:
And that means *ptr or (*ptr)[0] will give me the address of the first element
*ptr will do that. (*ptr)[0] will de-reference the array pointer and then dereference the resulting array, giving you the value of the first item, 1.
Similarly, (*ptr)[1]) will first give you an array and then the second item in that array, 2.
So as I understand *ptr[1] will give the address of the second element, and not it's value.
No, since [] has higher precedence than *, ptr[1] will first give you (the address of) the second array. Then you dereference that and you'll get the the value of the first item in the second array, 4.
The key here is that once you de-reference a pointer to an array, you end up with an array - behaving just like any array would in terms of "array decay" etc.
Best practices:
Do not de-reference array pointers with * if you can avoid it. ptr[0][0] is much less ambiguous. That syntax is the whole point of using array pointers in this case to begin with.
Avoid sloppy initializer lists like int a[][3]={1,2,3,4,5,6};. C allows it but it is bad style and mutes some possibilities of diagnostics. Instead this should have been int a[][3]={ {1,2,3}, {4,5,6} }; which as a bonus is also readable, self-documenting code.

First, it's a good idea to enable compiler warnings. Then you will be informed about missing braces in the initializer. Here is a slightly cleaned up version of your program:
#include <stdio.h>
int main(void)
{
int a[][3] = {{1, 2, 3}, {4, 5, 6}};
int (*ptr)[3] = a;
printf("%d\n", (*ptr)[1]);
return 0;
}
If you run it you will get the output "2". This is because *ptr is the first element of the array a, which itself is an array, and (*ptr)[1] is therefor the second element in this contained array which is 2.

Let's consider the expression used in the call of printf
printf(" %d",(*ptr)[1]) ;
For starters the pointer ptr points to the first element of the type int[3] of the two-dimensional array .
int (*ptr)[3]=a;
That is due to the initializer list
int a[][3]={1,2,3,4,5,6};
the two-dimensional array has two elements of the type int[3].
So dereferencing the pointer *ptr you get an lvalue of the type int[3] that is a one-dimensional array. Then to this array there is applied the subscript operator ( *ptr )[1] that yields the second element of the one-dimensional array.
So the value 2 will be outputted.
And that means *ptr or (*ptr)[0] will give me the address of the first
element
The expression *ptr and ( *ptr )[0] are two entities of different types.The expression*ptryields lvalue of the typeint[3]` , Use din expressions it is in turn can be implicitly converted to a pointer to teh first element of the obtained array.
The expression ( *ptr )[0] yields the first scalar element of the obtained array of the type int.
So as I understand *ptr[1] will give the address of the second
element, and not it's value.
The expression ptr[1] yields the second element of the type int[3] of the two-dimensional array In this expression *ptr[1] the obtained object of the type int[3] is implicitly converted to pointer of the type int * and dereferencing the pointer yields the first element of the type int of the second element of the two-dimensional array.
To make in more clear consider how the subscript operator is evaluated.
For example the expression ptr[0] is equivalent to *( ptr + 0 ) that in turn is equivalent to *ptr.
The expression (*ptr)[1] is equivalent to ptr[0][1].
The expression *ptr[1] is equivalent to *(ptr[1] ) that in turn is equivalent to ptr[1][0].
In general the expression ptr[i][j] can be rewritten in several ways. For example
( *( ptr + i ) )[j]
*( *( ptr + i ) + j )
*( ptr[i] + j )

Related

How a pointer to an array works in this context?

I was asked by an interviewer what the following C program will output
int a[5] = {1,2,3,4,5};
int *prt = (int*) (&a+1);
printf("%d %d", *(a+1), *(prt-1));
which prints
2 5
My answer was wrong for the second number. I realize that I don't really understand what's going on with a pointer to an array (which is already a pointer to the first element of the array). What is *ptr really doing here?
The type of the expression
&a
is int ( * )[5] and the expression
&a + 1
points to the memory past the last element of the array.
Then this pointer is interpreted as a pointer of the type int *.
(int*) (&a+1)
So this expression
(prt-1)
points to the last element of the array and the last element is outputted using the expression
*(prt-1)
This expression
(a+1)
points to the second element of the array and this element is outputted using the expression
*(a+1)

Why application of indirection to a two-dimensional array gives a pointer?

After reading some posts on this site, I realized that array in C isn't just a constant pointer as I originaly thought, but is itself a distinct type, but in most cases array "decays" to a constant pointer to the first element of the array. Because of this new information, a question arised in my mind. Suppose we have a two-dimensional A[10][10]. Why is the result of the expression *A a pointer to the first element of the array ? I thought that in this expression, A decays to a constant pointer to the first element of the array A[0][0], and then the application of the indirection should give us the value of the A[0][0], but in fact it still gives us the address of the first element of the array. Certainly, something is wrong with my logic or my understanding of the arrays or pointers, so where do I get it wrong ?
Thanks in advance.
The first element of A is A[0], not A[0][0].
This is because A is an array of ten things. C does not have two-dimensional arrays as a primary type. An array with multiple dimensions is derived or constructed as multiple layers of arrays. To the compiler, the resulting type is still just an array, whose elements happen to be further arrays.
Thus, in *A:
A is converted to a pointer to its first element. That pointer is &A[0], so *A becomes *&A[0].
* and & cancel, so the expression becomes A[0].
A[0] is an array of ten elements, so it is converted to a pointer to its first element, &A[0][0].
*A, or A[0], is itself an array of 10 elements and and array is always expressed by a pointer to its first element. However A[10][10] (let's say an array of ints) is effectively a block of memory holding 100 ints, the 10 of the first row followed by the 10 of the second row and so on. But if the expression *A or A[0] would return an int instead of a ptr to that row, it would be impossible to use the expression A[0][0], right ?
However, because such multidimensional array is a single block of memory, it's also possible to cast it to a pointer and then access it with an expression of this kind :
((int *)A)[iRow * 10 + iCol];
Which is equivalent to the expression :
A[iRow][iCol];
But this if it's possible for a 2D array declared this way :
int main()
{
int A[10][10] = { 0 };
A[9][9] = 9999;
printf("==> %d\n", ((int *)A)[9 * 10 + 9]); //==> 9999
return 0;
}
It is not if the memory is potentially made of separate blocks of bytes (probably requiring several calls to malloc) as with this kind of expressions :
int * A[10]; // or
int ** A;
A decays to a constant pointer to the first element of the array
A[0][0]
No, it does not. Why?
C standard specifies that *(pointer + integer) == pointer[integer] so the *A is an equivalent of *(A + 0) which is A[0]. A[0] will not give you the element A[0][0] only the single dimensional array which will decay to pointer to the first element of the first row of this array.

Are a, &a, *a, a[0], &a[0] and &a[0][0] identical pointers?

I have the following C program:
#include <stdio.h>
int main(){
int a[2][2] = {1, 2, 3, 4};
printf("a:%p, &a:%p, *a:%p \n", a, &a, *a);
printf("a[0]:%p, &a[0]:%p \n", a[0], &a[0]);
printf("&a[0][0]:%p \n", &a[0][0]);
return 0;
}
It gives the following output:
a:0028FEAC, &a:0028FEAC, *a:0028FEAC
a[0]:0028FEAC, &a[0]:0028FEAC
&a[0][0]:0028FEAC
I am not able to understand why are &a, a, *a - all identical. The same for a[0], &a[0] and &a[0][0].
EDIT:
Thanks to the answers, I've understood the reason why these values are coming out to be equal. This line from the book by Kernighan & Ritchie turned out to be the key to my question:
the name of an array is a synonym for the location of the initial element.
So, by this, we get
a = &a[0], and
a[0] = &a[0][0] (considering a as an array of arrays)
Intuitively, now the reason is clear behind the output. But, considering how pointers are implemented in C, I can't understand how a and &a are equal. I am assuming that there is a variable a in memory which points to the array(and the starting address of this array-memory-block would be the value of this variable a).
But, when we do &a, doesn't that mean taking the address of the memory location where the variable a was stored? Why are these values equal then?
They're not identical pointers. They're pointers of distinct types that all point to the same memory location. Same value (sort of), different types.
A 2-dimensional array in C is nothing more or less than an array of arrays.
The object a is of type int[2][2], or 2-element array of 2-element array of int.
Any expression of array type is, in most but not all contexts, implicitly converted to ("decays" to) a pointer to the array object's first element. So the expression a, unless it's the operand of unary & or sizeof, is of type int(*)[2], and is equivalent to &a[0] (or &(a[0]) if that's clearer). It becomes a pointer to row 0 of the 2-dimensional array. It's important to remember that this is a pointer value (or equivalently an address), not a pointer object; there is no pointer object here unless you explicitly create one.
So looking at the several expressions you asked about:
&a is the address of the entire array object; it's a pointer expression of type int(*)[2][2].
a is the name of the array. As discussed above, it "decays" to a pointer to the first element (row) of the array object. It's a pointer expression of type int(*)[2].
*a dereferences the pointer expression a. Since a (after it decays) is a pointer to an array of 2 ints, *a is an array of 2 ints. Since that's an array type, it decays (in most but not all contexts) to a pointer to the first element of the array object. So it's of type int*. *a is equivalent to &a[0][0].
&a[0] is the address of the first (0th) row of the array object. It's of type int(*)[2]. a[0] is an array object; it doesn't decay to a pointer because it's the direct operand of unary &.
&a[0][0] is the address of element 0 of row 0 of the array object. It's of type int*.
All of these pointer expressions refer to the same location in memory. That location is the beginning of the array object a; it's also the beginning of the array object a[0] and of the int object a[0][0].
The correct way to print a pointer value is to use the "%p" format and to convert the pointer value to void*:
printf("&a = %p\n", (void*)&a);
printf("a = %p\n", (void*)a);
printf("*a = %p\n", (void*)*a);
/* and so forth */
This conversion to void* yields a "raw" address that specifies only a location in memory, not what type of object is at that location. So if you have multiple pointers of different types that point to objects that begin at the same memory location, converting them all to void* yields the same value.
(I've glossed over the inner workings of the [] indexing operator. The expression x[y] is by definition equivalent to *(x+y), where x is a pointer (possibly the result of the implicit conversion of an array) and y is an integer. Or vice versa, but that's ugly; arr[0] and 0[arr] are equivalent, but that's useful only if you're writing deliberately obfuscated code. If we account for that equivalence, it takes a paragraph or so to describe what a[0][0] means, and this answer is probably already too long.)
For the sake of completeness the three contexts in which an expression of array type is not implicitly converted to a pointer to the array's first element are:
When it's the operand of unary &, so &arr yields the address of the entire array object;
When it's the operand of sizeof, so sizeof arr yields the size in bytes of the array object, not the size of a pointer; and
When it's a string literal in an initializer used to initialize an array (sub-)object, so char s[6] = "hello"; copies the array value into s rather than nonsensically initializing an array object with a pointer value. This last exception doesn't apply to the code you're asking about.
(The N1570 draft of the 2011 ISO C standard incorrectly states that _Alignof is a fourth exception; this is incorrect, since _Alignof can only be applied to a parenthesized type name, not to a expression. The error is corrected in the final C11 standard.)
Recommended reading: Section 6 of the comp.lang.c FAQ.
Because all expressions are pointing to the beginning of the array:
a = {{a00},{a01},{a10},{a11}}
a points to the array, just because it is an array, so a == &a[0]
and &a[0][0] is positioned at the first cell of the 2D array.
+------------------------------+
| a[0][0] <-- a[0] <-- a | // <--&a, a,*a, &a[0],&a[0][0]
|_a[0][1]_ |
| a[1][0] <-- a[1] |
| a[1][1] |
+------------------------------+
It is printing out the same values because they all are pointing to the same location.
Having said that,
&a[i][i] is of type int * which is a pointer to an integer.
a and &a[0] have the type int(*)[2] which indicates a pointer to an array of 2 ints.
&a has the type of int(*)[2][2] which indicates a pointer to a 2-D array or a pointer to an array of two elements in which each element is an array of 2-ints.
So, all of them are of different type and behave differently if you start doing pointer arithmetic on them.
(&a[0][1] + 1) points to the next integer element in the 2-D array i.e. to a[0][1]
&a[0] + 1 points to the next array of integers i.e. to a[1][0]
&a + 1 points to the next 2-D array which is non-existent in this case, but would be a[2][0] if present.
You know that a is the address of the first element of your array and according to the C standard, a[X] is equal to *(a + X).
So:
&a[0] == a because &a[0] is the same as &(*(a + 0)) = &(*a) = a.
&a[0][0] == a because &a[0][0] is the same as &(*(*(a + 0) + 0))) = &(*a) = a
A 2D array in C is treated as a 1D array whose elements are 1D arrays (the rows).
For example, a 4x3 array of T (where "T" is some data type) may
be declared by: T a[4][3], and described by the following
scheme:
+-----+-----+-----+
a == a[0] ---> | a00 | a01 | a02 |
+-----+-----+-----+
+-----+-----+-----+
a[1] ---> | a10 | a11 | a12 |
+-----+-----+-----+
+-----+-----+-----+
a[2] ---> | a20 | a21 | a22 |
+-----+-----+-----+
+-----+-----+-----+
a[3] ---> | a30 | a31 | a32 |
+-----+-----+-----+
Also the array elements are stored in memory row after row.
Prepending the T and appending the [3] to a we have an array of 3 elements of type T. But, the name a[4] is itself an array indicating that there are 4 elements each being an array of 3 elements. Hence we have an array of 4 arrays of 3 elements each.
Now it is clear that a points to the first element (a[0]) of a[4] . On the Other hand &a[0] will give the address of first element (a[0]) of a[4] and &a[0][0] will give the address of 0th row (a00 | a01 | a02) of array a[4][3]. &a will give the address of 2D array a[3][4]. *a decays to pointers to a[0][0].
Note that a is not a pointer to a[0][0]; instead it is a pointer to a[0].
Hence
G1: a and &a[0] are equivalent.
G2: *a, a[0]and &a[0][0] are equivalent.
G3: &a (gives the address of 2D array a[3][4]).
But group G1, G2 and G3 are not identical although they are giving the same result (and I explained above why it is giving same result).
This also means that in C arrays have no overhead. In some other languages the structure of arrays is
&a --> overhead
more overhead
&a[0] --> element 0
element 1
element 2
...
and &a != &a[0]
Intuitively, now the reason is clear behind the output. But, considering how pointers are implemented in C, I can't understand how a and &a are equal. I am assuming that there is a variable a in memory which points to the array(and the starting address of this array-memory-block would be the value of this variable a).
Well, no. There is no such thing as an address stored anywhere in memory. There is only memory allocated for the raw data, and that's it. What happens is, when you use a naked a, it immediately decays into a pointer to the first element, giving the impression that the 'value' of a were the address, but the only value of a is the raw array storage.
As a matter of fact, a and &a are different, but only in type, not in value. Let's make it a bit easier by using 1D arrays to clarify this point:
bool foo(int (*a)[2]) { //a function expecting a pointer to an array of two elements
return (*a)[0] == (*a)[1]; //a pointer to an array needs to be dereferenced to access its elements
}
bool bar(int (*a)[3]); //a function expecting a pointer to an array of three elements
bool baz(int *a) { //a function expecting a pointer to an integer, which is typically used to access arrays.
return a[0] == a[1]; //this uses pointer arithmetic to access the elements
}
int z[2];
assert((size_t)z == (size_t)&z); //the value of both is the address of the first element.
foo(&z); //This works, we pass a pointer to an array of two elements.
//bar(&z); //Error, bar expects a pointer to an array of three elements.
//baz(&z); //Error, baz expects a pointer to an int
//foo(z); //Error, foo expects a pointer to an array
//bar(z); //Error, bar expects a pointer to an array
baz(z); //Ok, the name of an array easily decays into a pointer to its first element.
As you see, a and &a behave very differently, even though they share the same value.

Array Declaration and pointer assignment in C

I am confused in the basics of pointer and array declaration in C. I want to know the difference between following two statements except that base address to array is assigned to ptr in seconed statement.
int a[2][3]= { (1,2,3),(4,5,6)};
int (*ptr)[3] = &a[0];
Please quote examples to clarify.
What effect do [3] on R side of line 2 has?
1. Bidimensional array:
int a[2][3]= { {1,2,3},{4,5,6}};
With this statement in memory you have 2x3 integers, all adjacent in memory.I suppose that you know how to access them, but in the case you don't I'll clarify it:
a[0][0] : 1
a[0][1] : 2
a[0][2] : 3
a[1][0] : 4
a[1][1] : 5
a[1][2] : 6
2. Pointer to array:
int (*ptr)[3] = &a[0];
ptr points to a int[3] block of memory.So you can assign it only to an int[3] type:
ptr= &a[0];
ptr= &a[1];
The difference is that this pointer does not have it's own memory, and you have to assign it to an int[3] variable or allocate it:
ptr= malloc (2*sizeof(int[3]);
This way you can use the memory pointed by ptr, if you initialize ptr this way:
for(int j=0; j<2; j++)
for(int i=0; i<3;i++)
ptr[j][i]=i+j*3+1;
This case you'll have the same memory representation of int a[2][3], except that this memory is in the heap and not in the stack.You can always choose to realloc/free the memory and this memory is not deleted once your function terminates.
You should know operator precedence rules in C: http://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedencehttp://en.wikipedia.org/wiki/Operators_in_C_and_C%2B%2B#Operator_precedence
int (*ptr)[3] as opposed to int * ptr [3]
The first one is a pointer (notice * is closer to the var name) to arrays of int of size 3
The second one is equal to int (*(ptr [3])) which is an array of size 3 on int pointers.
You can also use this site: http://cdecl.org/ if you have doubts on how to interpret an expression.
a is 2-D array of row size 2 and column size 3.
whereas ptr is pointer to an array of int having size 3
But your array ainitialization is not in correct manner
Since you have used () so comma operator will be in effect and will initialize with 3and 6 and other elements of array a will be 0 to do actual initialization use {}
&a[0] is address of first element of array (means it will print same value for a also).
but this &a[0] comes into effect when you perform pointer arithmetic operation on ptr
In case of array there are 3 things to keep in mind :
---> int *ptr=&a[0][0]; Address of first element ptr++ will give you next element a[0][1]
---> &a[0] = address of first element but if you do int (*ptr)[3]=&a[0]
then by doing ptr++ pointer will be increased by the size of whole row and ptr will point to next row directly means now ptr will point to &a[1]
---> &a = address of whole array and if you keep it in int (*ptr)[2][3] =&a and do ptr++ pointer will be increased by the size of whole array.

Problems with 2 D arrays

I wrote the following code in C:
#include<stdio.h>
int main()
{
int a[10][10]={1};
//------------------------
printf("%d\n",&a);
printf("%d\n",a);
printf("%d\n",*a);
//-------------------------
printf("%d",**a);
return 0;
}
With the above 3 printf statements I got the same value. On my machine it's 2686384. But with the last statement I got 1.
Isn't it something going wrong? These statements mean:
The address of a is 2686384
The value stored in a is 2686384
the value that is stored at address of variable pointed by a (i.e. at 2686384) is 2686384.
This means a must be something like a variable pointing towards itself...
Then why is the output of *(*a) 1? Why isn't it evaluated as *(*a)=*(2686384)=2686384?
#include<stdio.h>
int main()
{
// a[row][col]
int a[2][2]={ {9, 2}, {3, 4} };
// in C, multidimensional arrays are really one dimensional, but
// syntax alows us to access it as a two dimensional (like here).
//------------------------
printf("&a = %d\n",&a);
printf("a = %d\n",a);
printf("*a = %d\n",*a);
//-------------------------
// Thing to have in mind here, that may be confusing is:
// since we can access array values through 2 dimensions,
// we need 2 stars(asterisk), right? Right.
// So as a consistency in this aproach,
// even if we are asking for first value,
// we have to use 2 dimensional (we have a 2D array)
// access syntax - 2 stars.
printf("**a = %d\n", **a ); // this says a[0][0] or *(*(a+0)+0)
printf("**(a+1) = %d\n", **(a+1) ); // a[1][0] or *(*(a+1)+0)
printf("*(*(a+1)+1) = %d\n", *(*(a+1)+1) ); // a[1][1] or *(*(a+1)+1)
// a[1] gives us the value on that position,
// since that value is pointer, &a[i] returns a pointer value
printf("&a[1] = %d\n", &a[1]);
// When we add int to a pointer (eg. a+1),
// really we are adding the lenth of a type
// to which pointer is directing - here we go to the next element in an array.
// In C, you can manipulate array variables practically like pointers.
// Example: littleFunction(int [] arr) accepts pointers to int, and it works vice versa,
// littleFunction(int* arr) accepts array of int.
int b = 8;
printf("b = %d\n", *&b);
return 0;
}
An expression consisting the the name of an array can decay to a pointer to the first element of the array. So even though a has type int[10][10], it can decay to int(*)[10].
Now, this decay happens in the expression *a. Consequently the expression has type int[10]. Repeating the same logic, this again decays to int*, and so **a is an int, which is moreover the first element of the first element of the array a, i.e. 1.
The other three print statements print out the address of, respectively, the array, the first element of the array, and the first element of the first element of the array (which are of course all the same address, just different types).
First, a word on arrays...
Except when it is the operand0 of the sizeof, _Alignof, or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element in the array.
The expression &a has type "pointer to 10-element array of 10-element array of int", or int (*)[10][10]. The expression a has type "10-element array of 10-element array of int", which by the rule above decays to "pointer to 10-element array of int", or int (*)[10]. And finally, the expression *a (which is equivalent to a[0]) has type "10-element array of int", which again by the rule above decays to "pointer to int".
All three expressions have the same value because the address of an array and the address of its first element are the same: &a[0][0] == a[0] == *a == a == &a. However, the types of the expressions are different, which matters when doing pointer arithmetic. For example, if I have the following declarations:
int (*ap0)[10][10] = &a;
int (*ap1)[10] = a;
int *ip = *a;
then ap0++ would advance ap0 to point to the next 10x10 array of int, ap1++ would advance ap1 to pointer to the next 10-element array of int (or a[1]), and ip++ would advance ip to point to the next int (&a[0][1]).
**a is equivalent to *a[0] which is equivalent to a[0][0]. which is the value of the first element of a and has type int and the value 1 (note that only a[0][0] is initialized to 1; all remaining elements are initialized to 0).
Note that you should use %p to print out pointer values:
printf("&a = %p\n", &a);
printf(" a = %p\n", a);
printf("*a = %p\n", *a);
First of all, if you want to print out pointer values, use %p - if you're on a 64 bit machine int almost certainly is smaller than a pointer.
**a is double dereferencing what's effectively a int**, so you end up with what the first element of the first sub-array is: 1.
If you define a as T a[10] (where T is some typedef), then a simple unadorned a means the address of the start of the array, the same as &a[0]. They both have type T*.
&a is also the address of the start of the array, but it has type T**.
Things become trickier in the presence of multi-dimensional arrays. To see what is happening, it is easier to break things down into smaller chunks using typedefs. So, you effectively wrote
typedef int array10[10];
array10 a[10];
[Exercise to reader: What is the type of a? (it is not int**)]
**a correctly evaluates to the first int in the array a.
From C99 Std
Consider the array object defined by the declaration
int x[3][5];
Here x is a 3 × 5 array of ints; more precisely, x is an array of three element objects, each of which is an array of five ints. In the expression x[i], which is equivalent to (*((x)+(i))), x is first converted to a pointer to the initial array of five ints. Then i is adjusted according to the type of x, which conceptually entails multiplying i by the size of the object to which the pointer points, namely an array of five int objects. The results are added and indirection is applied to yield an array of five ints. When used in the expression x[i][j], that array is in turn converted to a pointer to the first of the ints, so x[i][j] yields an int.
so,
Initial array will be x[0][0] only.
all x, &x and *x will be pointing to x[0][0].
No, there's nothing wrong with your code. Just they way you are thinking about it... The more I think about it the harder I realize this is to explain, so before I go in to this, keep these points in mind:
arrays are not pointers, don't think of them that way, they are different types.
the [] is an operator. It's a shift and deference operator, so when I write printf("%d",array[3]); I am shifting and deferencing
So an array (lets think about 1 dimension to start) is somewhere in memory:
int arr[10] = {1};
//Some where in memory---> 0x80001f23
[1][1][1][1][1][1][1][1][1][1]
So if I say:
*arr; //this gives the value 1
Why? because it's the same as arr[0] it gives us the value at the address which is the start of the array. This implies that:
arr; // this is the address of the start of the array
So what does this give us?
&arr; //this will give us the address of the array.
//which IS the address of the start of the array
//this is where arrays and pointers really show some difference
So arr == &arr;. The "job" of an array is to hold data, the array will not "point" to anything else, because it's holding its own data. Period. A pointer on the other hand has the job to point to something else:
int *z; //the pointer holds the address of someone else's values
z = arr; //the pointer holds the address of the array
z != &z; //the pointer's address is a unique value telling us where the pointer resides
//the pointer's value is the address of the array
EDIT:
One more way to think about this:
int b; //this is integer type
&b; //this is the address of the int b, right?
int c[]; //this is the array of ints
&c; //this would be the address of the array, right?
So that's pretty understandable how about this:
*c; //that's the first element in the array
What does that line of code tell you? if I deference c, then I get an int. That means just plain c is an address. Since it's the start of the array it's the address of the array, thus:
c == &c;

Resources