What likely makes things confusing for you is that v
in main
is of a different type than v
in fn
. You probably knew that, but let's break down the differences. In main
, v
is a pointer to an array of 4 ints. In fn
, v
is a pointer to an int*
which from the context in main
, you know is that int*
is actually a pointer to an array of 4 elements.
You cannot know the true use case int** v
in fn
by looking at it. You have to know the context which is defined in main
.
In main
, you pass &v
into fn
. That gives you the correct int**
type. You have to consider what the use case of &v
is. It is not an array; but rather, it is a pointer to the address on the main stack that holds v
. You can think of &v
as a pointer to an array consisting of a single element whose type is int*
. Let's replace &v
with vv
.
Here is the change using vv
instead of v
to emphasize the differences. I've added extra lines of code for clarity.
#include <stdio.h>
#include <stdlib.h>
void fn(int** vv, int size) { // vv is pointer to a single int* element
int* v_fn = *vv; // v_fn now has the address of main's v.
for (int i = 0; i < size; i++) {
printf("%d @ %p\n", v_fn[i], &v_fn[i]);
}
}
int main() {
size_t sizeof_int = sizeof(int);
int* v = (int*)malloc(sizeof(int) * 4);
v[0] = 1;
v[1] = 2;
v[2] = 3;
v[3] = 4;
int** vv = &v; // vv is pointer to main's stack address of v.
fn(vv, 4); // you can think of vv as a pointer to an array of 1 element of type int*.
}
The output is:
sizeof_int = 4
1 @ 010161E8
2 @ 010161EC
3 @ 010161F0
4 @ 010161F4
and you see that the addresses increase by 4; namely, the size of int for my compiler on my PC.
(*v)[i]
, not*v[i]
(which means the same as*(v[i])
). But there's not really any reason for a double pointer (just trusting that there's a reason you haven't explained)int**
parameter in case you were doing something like placing that malloc call inside the function and need to return a pointer through the parameter. Which you aren't doing.