I was comparing various printf
to better understand the difference between int *
and int (*)[]
and how i can visualize various addresses and values.
In the following program i wrote one thing bothers me:
#include <stdio.h>
int main() {
int a[3] = {1,2,3};
int *p = a;
printf("address of a: %p\n", &a);
printf("\naddress of a[0]: %p\n", &a[0]);
printf("\nvalue of p: %p\n", p);
printf("\nvalue of *p: %d\n", *p);
printf("\nvalue of a[1]: %d\n", *(p + 1));
puts("\n\n-------------------\n\n");
int b[3] = {1,2,3};
int (*q)[3] = &b;
printf("address of b: %p\n", &b);
printf("\naddress of b[0]: %p\n", &b[0]);
printf("\nvalue of q: %p\n", q);
printf("\nvalue of *q: %p\n", *q);
}
In the first part p
, as a pointer, holds as value the address of a[0]
, so *p
holds as value 1
( printed with %d).
In the second part, though, q
seems to hold the same value of *q
(in this case i use %p), therefore i need to use **q
to print b[0]
.
How come?
The pointer q
points to an array of 3 integers. You can visualise it like this:
q -----> |b = {1,2,3}|
// q points to the whole array.
// note how it doesn't point to a specific element.
Your print statements broken down:
&b
- this is the base address of b
. |b = {1,2,3}| // address of whole array
&b[0]
- this is the address of the 0th
element of b
. b = {1,2,3}
^
// address of b[0]
q
- this points to the base address of b
and holds the same value as &b
. q -----> |b = {1,2,3}| // address of whole array
*q
- this will yield the address of the first element of b
, in your case this is the address of b[0]
. b = {1,2,3}
*q ---^
In regards to your question:
With q
you must dereference twice ( **q
) because:
q
points to the base address of b
*q
) it will yield the address of b[0]
.**q
) we will get the value in b[0]
.Here is a visualization that may help you understand how it works.
- q -----> |b = {1,2,3}| // points to base address of b
- *q ------------^ // points to address of b[0]
- **q -----------^ // value of b[0]
int*
you get an item of type int
.int (*q)[3]
you get an array of type int [3]
. Now, whenever you use an array in an expression (in most cases) it decays into a pointer to its first element. So *q
gives you an array int [3]
which then immediately decays into a pointer to the first element, type int*
. And that's the pointer you'll be printing. We can prove that this is the case by executing this snippet:
_Generic(*q,
int*: puts("we ended up with an int*"),
int(*)[3]: puts("this wont get printed") );
In order to print the value pointed at by that pointer, you therefore need another level of dereferencing: either (*q)[0]
or **q
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.