I'm just started studying C language with a book and is not getting bit confused on the part where they discuss pointers and arrays. If there is a multidimensional array(I'll just discuss this array as two-dimensional to be specific) called a[NUM_ROW][NUM_COLS], what does the a[0] mean?
The part I was studying had a part concerning "processing the rows of a multidimensional array" and it had example where
p = &a[i][0] ;
could be written as
p = a[i];
and the book said a[i] is a pointer to the first element in row i.
Then there was a part about "using the name of a multidimensional array as a pointer" where in the case of int a[NUM_ROWS][NUM_COLS], the array name a is not a pointer to a[0][0] but a pointer to a[0].
Does a[0] have same meaning as the a[i] in the first part? I am a bit confused because in the part about "using the name of a multidimensional array as a pointer" the books says array name a is a pointer to an integer array of length NUM_COLS(and a has type int (*) [NUM_COLS]
I was wondering if a[0] indicate the integer array of length NUM_COLS or a pointer to the first element in row 0. (Or is it the same thing? Maybe since I am a bit new to the concept and confused.)
P.S. the book is chapter 12.4 of C programming(KNK)
In general, the name of an array decays to a pointer to its first element. A multidimensional array is basically just an array of arrays, so when you have int a[NUM_ROW][NUM_COL], a[i] is the "name" of the i'th row.
So by the above rule, a[i] decays to a pointer to the first element of that row, which is a[i][0]. To create a pointer we put & before the expression, so that's &a[i][0].
And a decays to a pointer to the the first element of the 2-dimensional array. Each element of the main array is a row, not an individual integer, so a is equivalent to &a[0], not &a[0][0].
The memory location of a[0] and a[0][0] are the same, the difference is in the type of the expression. The type of a[0][0] is int, but the type of a[0] is int[NUM_COL], which will decay to int * in many contexts. This is easiest to see by using the typeof operator:
printf("size of a = %d, size of a[0] = %d, size of a[0][0] = %d\n", sizeof a, sizeof a[0], sizeof a[0][0]);
If NUM_ROW = 5 and NUM_COL = 10, this will probably print:
size of a = 200, size of a[0] = 40, size of a[0][0] = 4
Let's get this out of the way: Arrays and pointers are not one and the same. Array type is a different type. As an example, if you have a pointer int* ptr, ++ptr is perfectly valid (though it might not point to something valid), but if you have an array like int a[3], you may not increment it. But one constraint arrays have is, you may not pass arrays to functions and functions may not return array type. But what happens when you try? What happens is your array is implicitly converted to a pointer to its first element. That is where the confusion comes from: Arrays are converted to a pointer to their first element when you need a pointer pointing them. Therefore, ptr = a would mean ptr is now pointing to the first element of a.
Now let's assume we have this:
int arr[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
What is this exactly? It is an array of arrays. arr[i] refers to one of the answers though it usually decays to a pointer.
Related
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.
I am learning pointers and arrays in C and Here is a question that confused me for a while:
So the name of a 1D int array is a constant pointer to int, which points to the first element in that array. So when we evaluate the name of a 1D array, we should get the address of the first element in the array.
For a 2D int array, the array name is a pointer to the first array of int. So what will be the value of a 2D int array's name? I think it should be the address of the first array in this 2D array. But how is the address of an array defined in C? Is it just the address of the first element in that array?
So the name of a 1D int array is a constant pointer to int
This is wrong, and it is often taught badly. An array is an array. Here is some code for analogy:
int x = 5;
double d = x + 1.2;
In the second line x is converted to double for purposes of addition. This does not change x which is still an int, the result of conversion is "temporary" and only exists until the addition is finished. The conversion is demanded by the conditions of the + operator that both arithmetic operands must be brought to a common type (double in this case).
In the array case, say we have char *p = arrayname + 1 , then arrayname is still an array. But it is converted to a temporary pointer so that the addition can occur (the + operator requires this, it can add a pointer and an integer). The temporary pointer points to the first element of the array, but it is not correct to say that the temporary pointer is the array.
Most operators invoke this conversion of an array to a temporary pointer, but some do not. So it is not correct to say that arrayname is a pointer because it may be used with an operator that does not convert the array to a pointer, e.g. sizeof arrayname.
The result of converting an array to a pointer is a pointer to the first element of that array. This is always true even if the first element is itself an array.
But how is the address of an array defined in C? Is it just the address of the first element in that array?
No. Every variable has an address, this applies to arrays and non-arrays. If you understand the address of an int then you also understand the address of a 2x2 array of char.
Let's clear up some things:
int a = 24;
The above is many things:
a declaration: we declare a variable named a of type int.
a definition: an object of type int is created.
an initialization: this object is initialized with the value 24
So let's recap: an object of type int is created with the value 24 and the variable a names it.
Now let's apply the same to the following:
int a1[3] = {0, 1, 2};
a declaration: we declare a variable named a1 of type int[3] (aka array of 3 integers).
a definition: an object of type "array of 3 integers" is created
an initialization: the object is initialized with {0, 1, 2}
The variable a1 names that object.
So the name of a 1D int array is a constant pointer to int, which
points to the first element in that array.
Wrong. I know you might have been told or read this, but it is incorrect. An array is not a pointer!! Arrays and pointers are different types. That being said, for convenience and historical reasons, in most situations (but not all!) an array decays to a pointer to the first element:
int a1[3] = {0, 1, 2};
int* p = a1; // here a1 decays to a pointer to its first element
In the above snippet p points to the element 0 of the array a1
You can view 2D or 3D or nD array the same way:
T a2[3] = {l0, l1, l2};
Let's say T is a type. The above is an "array of 3 Ts".
if T is int then we have int a2[3] = {0, 1, 2} - an array of 3 integers. We call this an 1D int array.
but if T is int[2] then the above becomes int a2[3][2] = {{00, 01}, {10, 11}, {20, 21}} - you can see it as "an array of 3 Ts" or "an array of 3 int[2]" or "an array of 3 arrays of 2 integers".
And we can apply the same decaying rule:
int a2[3][2] = {{00, 01}, {10, 11}, {20, 21}};
int (*p2)[2] = a2; // a2 decays to a pointer to its first element.
// Its first element is an array of 2 int.
// So a2 decays to `int (*)[2]` - a pointer to an array of two elements.
In the above a2 points to the element {00, 01} of the array.
An arrays name is not a pointer. In most cases when the name of an array is used, it gets implicitly *converted* to a pointer to its first element, it is said, that the array decays into a pointer.
The name of an array does not decay to a pointer when it is the argument of the address-of operator (&), the sizeof-operator and when a string literal (which is an array of some character type) is used to initialize an array *).
That said, a two-dimensional arrays
T arr[COLS][ROWS];
first element is an array of type T[ROWS]. So arr decays to a pointer of type T(*)[ROWS] which points to the first element of arr.
*) If you might want to add that arrays also do not decay when they're the operand of the _Alignof-operator or read that somewhere else:
#EricPostpischi: Arrays cannot be operands of _Alignof. Including _Alignof in the exceptions for array conversion was an error in the C 2011 standard. _Alignof operands can only be types, not expressions.
When a 2D array decays to a pointer, you have a pointer to an array. Here's an example of what this would look like:
int arr[5][6];
int (*p)[6] = arr;
An array is not a pointer. An array's name, when used in an expression, "decays" into a pointer to the first element.
Strictly speaking, C only has one-dimensional arrays, and a 2D array is really just an array of arrays.
1D array:
The first element of int arr [x], is an int.
When arr is used in an expression, you get a pointer to that element, int*.
When doing pointer arithmetic on this pointer, each item has the size of the first element = sizeof(arr[0]).
2D array:
The first element of int arr [x][y] is an int [y].
When arr is used in an expression, you get a pointer to that element, int (*)[y].
When doing pointer arithmetic on this pointer, each item has the size of the first element = sizeof(arr[0]).
So it's the same rule. The int(*)[y] array pointer follows the same rules of pointer arithmetic as the ordinary pointer. But you can de-reference it one step further to get individual int in the array of arrays.
"So what will be the value of a 2D int array's name?"
"I actually understand that an array is not a pointer. In my question,
what I actually mean is that when the name of an array is used in an
expression, the compiler will generate the pointer constant."
You have to be careful here. As a follow-on to your comment below your question, there are nuances in how the array/pointer conversion rules apply that effect the type that results from the conversion. That will dictate whether and how you can use the array name in an expression.
"... the compiler will generate the pointer constant."
No. The compiler does not generate a pointer constant, the compiler follows C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3). When the array name is used in an expression, the expression is evaluated with the address that results from the conversion of the array to a pointer (subject to the 4-exceptions stated in paragraph 3).
The rule regarding array/pointer conversion does not depend on number of dimensions, the rule is applied the same regardless. However, the type of the pointer that results from the conversion does depend on the number of array dimensions. That is critical and that will dictate whether your use of the array name is valid.
One way to help cement what is happening in the conversion is take it step-by-step. Start with a 1D array and work your way up.
6.3.2.1 - 1D Array Conversion To Pointer On Access
When you have a simple array, e.g.
int array[10];
On access to array, is converted to a pointer to the first element, e.g., the address of the element, &array[0]. (which is simply a pointer to int, or with formal type int *)
6.3.2.1 - 2D Array Conversion To Pointer On Access
With a 2D array, rule applies just the same, e.g.
int array[10][10];
Here array, a 2D array, is essentially an array of 10 - int[10] arrays (an array of 1D arrays). On access array[10][10] is converted to a pointer to the first array of 10-int in exactly the same manner, &array[0][0] (which results in a pointer to an array of int[10] or with formal type int (*)[10]) It is not a pointer-to-pointer (e.g. int**), it is very specifically a pointer to an array of int[10].
(note the important difference between int *[10] (an array of 10 pointers which on access will become a pointer-to-pointer) and int (*)[10] (a pointer to array of 10 int))
Answer
"So ... the value of a 2D int array's name when used in an expression" -- is the address of the first 1D array of integers that make up the 2D array with formal type int (*)[N] (where N is the number of elements per-row).
Nuance In How The Standard Is Applied
The type is critical for the proper use of the array name. With a 2D array, the resulting address is a pointer to an array. What results if you dereference that pointer? (Answer: an array) What happens when you access that array through the derefernced pointer? (hint: the conversion on access rules apply again). You must know what the pointer type resulting from the conversion will be in order to properly use the array name in an expression.
An Example May Help
Or it may not, but working with the pointer types that result from the array access and pointer conversion may help things sink in. Below, the example declares a simple 4x3 2D array of int. It then declares a pointer (p) of proper type to allow the array name to be used in an expression assigning the array address to the pointer. The pointer initialized with the array name is then used to further initialize an integer pointer (ip) to the first element in the first array.
The example then outputs the address for each element, and then using the pointer p outputs the address of the beginning of each row-array that makes up the 2D array. Finally the code enters a validation loop comparing the addresses of each element by (1) array index, (2) the address held by pointer p using an offset, and (3) address held by ip. The purpose being the use of each of the different pointers resulting from the expression assigning the array name to then reference each element and ensuring the addresses held by each pointer agree.
#include <stdio.h>
int main (void) {
int array[ ][3] = { {1, 2, 3}, /* 2D array values */
{3, 4, 5},
{5, 6, 7},
{7, 8, 9} },
(*p)[3] = array, /* pointer to array */
*ip = *p; /* integer poiner */
size_t size = sizeof array,
nele = size / sizeof **array,
nrow = size / sizeof *array,
ncol = sizeof *array / sizeof **array;
printf ("2D array statistics:\n\n"
" size: %zu (bytes)\n nele: %zu (ints)\n"
" nrow: %zu\n ncol: %zu\n",
size, nele, nrow, ncol);
puts ("\naddress of each array element:\n");
for (size_t i = 0; i < nrow; i++) {
for (size_t j = 0; j < ncol; j++)
printf (" %p", (void*)&array[i][j]);
putchar ('\n');
}
puts ("\naddress of each 1D array:\n");
for (size_t i = 0; i < nrow; i++)
printf (" %p\n", (void*)p[i]);
puts ("\nvalidating each array element address by index & pointer:\n");
for (size_t i = 0; i < nrow; i++) {
for (size_t j = 0; j < ncol; j++) {
if (ip != &array[i][j] || ip != *p + j) {
fprintf (stderr, "address validation failed for "
"array[%zu][%zu]\n(%p != %p || %p != %p)\n",
i, j, (void*)ip, (void*)&array[i][j],
(void*)ip, (void*)(p + j));
return 1;
}
ip++;
}
p++;
}
puts (" done!");
return 0;
}
Example Use/Output
$ ./bin/array_2d_access
2D array statistics:
size: 48 (bytes)
nele: 12 (ints)
nrow: 4
ncol: 3
address of each array element:
0x7ffe7c9a9780 0x7ffe7c9a9784 0x7ffe7c9a9788
0x7ffe7c9a978c 0x7ffe7c9a9790 0x7ffe7c9a9794
0x7ffe7c9a9798 0x7ffe7c9a979c 0x7ffe7c9a97a0
0x7ffe7c9a97a4 0x7ffe7c9a97a8 0x7ffe7c9a97ac
address of each 1D array:
0x7ffe7c9a9780
0x7ffe7c9a978c
0x7ffe7c9a9798
0x7ffe7c9a97a4
validating each array element address by index & pointer:
done!
Let me know if that helped and whether you have any further questions.
This is an extended question from the answer by "Some programmer dude" in this forum.
Accessing 2D array elements using pointer arithmetic in C
To quote the answerer,
&s[0][0]. This is of type int *.
&s[0]. This is of type int (*)[2].
s[0]. This will decay to a pointer to the first element in s[0], and is equal to 1.
s. This will decay to a pointer to the first element in s, and is equal to 2.
&s. A pointer to the array, of type int (*)[4][2].
I don't get why 3 equals 1 and 4 equals 2?
I thought 3 equals 2 and 4 equals 5.
For example, putting s[0] will give the address of s[0] since it's an array, hence s[0] = &s[0].
Let's take a look at your 2D array and consider the types of the various variables you've asked about:
int s[4][2] = {
{1234,56},
{1212,13},
{1434,80},
{1312,78}
};
Now:
s is a 2D array of ints.
s[0], s[1], etc. are arrays of int.
Your question states:
putting s[0] will give the address of s[0] since it's an array, hence
s[0] = &s[0]
This is not correct. When used in an expression, the name of an array decays to a pointer to the first element of the array. What is the first element of s? It is the entire array s[0].
Since s[0] is an array, it is equivalent to the address of its first element. What is the first element of the array s[0]? It is the int s[0][0]. So since the value of the array name s[0] when used in an expression is equivalent to the address of the first element of the array, i.e., to s[0][0], we have:
s[0] == &s[0][0]
This is why (3) in the answer you have quoted is equivalent to (1).
Similarly, s is equivalent to &s[0]. When used in an expression, the array name s decays to a pointer to the entire array s[0]; as a pointer to an array of two int elements, its type is int (*) [2]. Its value is the address of &s[0], i.e., the address of the entire array (not just of its first element). This is why (4) is equivalent to (2).
As "Some programmer dude" showed in the diagram in his answer to your original question, these various pointers might point to the same location in memory, but semantically they are quite different.
Hope this helps!
What is the difference between a pointer to an array and a pointer to the first element of an array? In most cases they would be same. Please specify an example when they are not the same. Thank you.
The type is different:
int x[1] = {0};
&x[0] is a pointer to the first element of x array and is of type int *.
&x is a pointer to x array and is of type int (*)[1].
But their value is the same because there is no padding in arrays:
(int *) &x == x /* in a value context the expression evaluates to 1 */
The identity of an object is given by the pair (address, type). Different objects can have the same address as long as their types are different, in which case one is a subobject of the other.
This is the case with arrays: The array is an object, and the array elements are objects, and the array elements are subobjects of the array. The first element happens to have the same address as the array itself. Something similar is true for structs and the first struct member.
So if you have an array T a[N], then the type of a is T[N] and the type of a[0] is T, and so the address of the array is
T (*array_addr)[N] = &a;
and the address of the first element is
T * elem_addr = &a[0];
Since a naked array expression decays to a pointer to the first element under certain conditions, the last line could also be written as T * elem_addr = a;, which has the exact same meaning.
The main difference is that when you obtain the reference to an array, it decays to a pointer and sizeof can't be used anymore on it to obtain the array size, eg:
int array[10];
printf("%d\n", sizeof(array)/sizeof(array[0]));
printf("%d\n", sizeof(&array)/sizeof(array[0]));
This prints on x64:
10
2
Of course you will lose any reference to the size of the array even if you convert to a pointer without any use of the & operator:
printf("%d\n", sizeof((int*)array)/sizeof(array[0])); // prints 2
you can print the a and &a, than print a++ and &a++. Through the result, you will know the answer, just try it. a means a element address, and &a means the array address. int a[] = {1, 2 };
Pointer to an array and pointer to the first element of an array is represented as q=&a and p=a. When you increment the p as p++ it will point to the next element in array but when you increment q++ it will give to the next location to the last element in that array. Thus pointer to an array represents to whole array while pointer to first element in array represents only to the first element in array.
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;