2

This is my code.

I'm allocating memory to a dynamic array and trying to print it with fn().

I won't be able to pass the array normally (like int *v) I can only pass it as int **v for specific reasons.

#include <stdio.h>
#include <stdlib.h>

void fn(int **v, int size) {
    for(int i = 0; i < size; i++)
        printf("%d @ %p\n", *v[i], &*v[i]);
}

int main() {
    int *v = (int*)malloc(sizeof(int) * 4);
    v[0] = 1;
    v[1] = 2;
    v[2] = 3;
    v[3] = 4;

    fn(&v, 4);
}
4
  • 5
    You need (*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)
    – Ben Voigt
    Commented Dec 3, 2024 at 23:45
  • You only need the 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.
    – Lundin
    Commented Dec 4, 2024 at 7:49
  • There is no array of arrays in your code. A pointer to a pointer is something very different.
    – Gerhardh
    Commented Dec 4, 2024 at 8:30
  • "I won't be able to..." How did you try to do this and what happened when you tried?
    – Gerhardh
    Commented Dec 4, 2024 at 8:30

2 Answers 2

2

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.

1

Rather than writing *v[i] which is equivalent to *(v[0]) you want to use (*v)[i].

You also don't want to cast malloc and should check that it succeeded before trying to use that memory.

The size parameter and your i variable in the loop should probably be of type size_t but I'm assuming you're force to respect the signature of fn.

#include <stdio.h>
#include <stdlib.h>

void fn(int **v, int size) {
    for(int i = 0; i < size; i++)
        printf("%d @ %p\n", (*v)[i], &(*v)[i]);
}

int main() {
    int *v = malloc(sizeof(int) * 4);
    if (!v) {
        fprintf(stderr, "Memory allocation problem.\n";
        return 1;
    }

    v[0] = 1;
    v[1] = 2;
    v[2] = 3;
    v[3] = 4;

    fn(&v, 4);
}

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.