Related
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 )
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.
The book that I have says that An array name is a pointer constant.
So, I tried this :
int A[3][4] = {0};
A[0][0] = 1;
A[1][0] = 2;
A[2][0] = 3;
printf("A : %x\n", A);
printf("*A : %x\n", *A);
I expected the result of first printf is the address of A and the other is 1.
because, I thought array name is a pointer constant and the result would be *(address of A).
but, the results have same value; address of A.
do you know why? please give me some advice.
First, arrays are not pointers! Your book is wrong. Arrays and pointers share some operations, and array name can be automatically converted to a pointer to its first element in some cases, but remember they are different.
Second, in your code, A is a 2-dimensional array, i.e, an array of arrays. so *A, which is the same as A[0], is its first subarray. To access A[0][0], you need **A.
Arrays are not pointers. Except when it is the operand of the sizeof or unary & operators, or is a string literal 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 of the array.
Given the declaration of A, all of the following are true:
Expression Type Decays to Value
---------- ---- --------- -----
A int [3][4] int (*)[4] &A[0][0]
*A int [4] int * &A[0][0]
&A int (*)[3][4] n/a &A[0][0]
A[i] int [4] int * &A[i][0]
*A[i] int n/a A[i][0]
&A[i] int (*)[4] n/a &A[i][0]
A decays to an expression of type "pointer to 4-element array of int". A[i] decays to an expression of type "pointer to int. The address of the first element of the array is the same as the address of the array itself, so the expressions
A
*A
&A
A[0]
&A[0]
&A[0][0]
all evaluate to the same value, but the types of the expressions will be different.
Array and pointers are not same.
The main difference is you cannot perform the pointer increment or decrement on the array name. You can think of array as constant pointer.
If you want to print the element of an array then try **A or *(A + i) in loop where i is the loop index
Don't confuse with array's and pointers! Both are different things! and also array is not a pointer! But array name represents base address of array!
In your code-
int A[3][4];
It is a 2D array so you need to dererence two times. If you dererence one time it will fetch the address of the array only. A, A[0], *A, &A, &A[0] all will represent the starting address of it.
Try -
printf("%d\n",**A);
or
printf("%d\n",A[0][0]);
or
printf("%d\n",*A[0]);
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;