Pointer to array of elements when dereferenced return an address. Since it is holding the address of the first element of the array, dereferencing it should return a value.
The question was
"Why does
*ptr
return the base address of the array, shouldn't it return the value at that address?"
It does return the value at that address, which is the array arr
.
Think about a queue of people: you can point to the first person and say "that person over there" or you can point to the same person and say "that queue over there". There are 2 things at the same location: a person and a queue. Same thing happens with arrays: person *
for that "person over there" and person (*)[42]
"for that queue of 42 people". If you dereference a pointer to queue, you get a queue. If you take the first from the queue you get a person.
But then the array itself will decay to address to the first element when it is given as an argument to printf
. Thus here,
int arr[] = { 3, 5, 6, 7, 9 };
int (*ptr)[5] = &arr;
// undefined behaviour really, all pointers should be cast to void *
printf("%p %p %p %p", *ptr, &ptr[0], arr, &arr[0]);
all these 4 expressions will result in pointer to int
, and the value is the address of the first element in the array (the address of 3 in arr
).
Here is a simple, less technical explanation.
How are you setting p
? = arr;
How are you setting ptr
? = &arr;
Your question really has nothing to do with arrays at all. arr
could be literally any type and the answer would be the same: &
gets the address of arr
, so whatever arr
is, ptr
is storing its address while p
is storing arr
itself.
If you do *ptr
, you will dereference that address and thus get a value equal to p
.
int arr = 3;
// clearly these are different!
int p = arr;
int* ptr = &arr;
Similarly
int x = 3;
int* arr = &x;
// clearly these are different!
int* p = arr;
int** ptr = &arr;
// so of course they dereference differently
printf("*p = %d, *ptr = %p\n", *p, *ptr);
The behavior you see is a result of 'c' interpreting arr
as a pointer to the memory location of the first element. Pointer to the array &arr
will be an address of the array itself in memory, which is also the address of its first element. As a result arr
and &arr
yield the same values. Try this:
printf("array = %p, &array = %p\n", arr, &arr);
Thought the values are the same, types are different. arr
is a variable, whether &arr
is a pointer to the variable.
ptr
reflects the same picture. Its value ptr = &arr
makes it a pointer to an array. It contains the address of the array. *ptr
returns the array itself, which in 'c' interpretation is the address of the first element of the array. As a result values for ptr
and *ptr
are the same as for &arr
and arr
.
Hope it makes it clearer (not murkier) :-)
Arrays are pointers. Arrays are not pointers, see the comments below
A pointer to an array is a pointer, pointing at a pointer. Try de-referencing twice over, that should yeild a value.
Why does *ptr return the base address of the array, shouldn't it return the value at that address??
(p3) Except when it is the operand of the sizeof
operator, the _Alignof
operator, or the unary '&'
operator, or is a string literal used to initialize an array, an expression that has type "array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object and is not an lvalue. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3)
int (*ptr)[5] = &arr;
ptr
is a pointer-to-array of int [5]
. When you dereference ptr
you get array of int[5]
. How is an array of int[5]
accessed?
Rule 6.3.2.1
provides the answer:
"array of type" is converted to an expression with type "pointer to type" that points to the initial element of the array object...
Now if you dereference again (e.g. **ptr
), then you get the value of the 1st element.