Why do I have to pass a pointer to a pointer in this case

364 Views Asked by At

This question is builds on a previous question from me.

There I had this construct. It uses SDL2:

void init_window(SDL_Window *window)
{
    window = SDL_CreateWindow(…);
}

int main(void)
{ 
    SDL_Window  *window;
    init_window(window);
}

This didn't work. The answer suggested, I used *&window as a function parameter instead, and it worked great. I rewrote the *&window to **window as the following:

void init_window(SDL_Window **window)
{
    *window = SDL_CreateWindow(…);
}

int main(void)
{ 
    SDL_Window  *window;
    init_window(&window);
}

And it also works. But I still don't understand why the first version doesn't work. I looked up the implementation details of SDL_Window and it's just a normal typedef of a struct to put it into ordinary namespace. SDL_CreateWindow returns SDL_Surface *.

To picture my dilemma, I wrote this simple program:

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

typedef struct Person
{
    char *name;
    int age;
} Person;

Person *person_create(char *name, int age)
{
    Person *who = malloc(sizeof(Person));
    who->name   = strdup(name);
    who->age    = age;

    return who;
}

void person_get_old(Person *who)
{
    who->age += 30;
}

int main(void)
{
    Person *susan = person_create("Susan", 23);
    person_get_old(susan);
    printf("%i\n", susan->age);
}

This prints 53 just as expected, without me having to use pointer to pointer semantics. What is the difference between my implementation and that one of SDL2. This is no SDL2 question, as the one that answered my previous question could answer this without any knowledge of SDL2, so there seems to be some implementation detail I missed. Hope somebody can enlighten me.

2

There are 2 best solutions below

0
On BEST ANSWER

Here's a simpler example to illustrate:

void foo(int p) //create new copy of int
{
    p = 0; //modify copy, original is unchanged
}
void bar(int* p) //create new copy of pointer
{
    *p = 0; //modify object pointer is set to
}

In your SDL example, you were trying to do foo. The goal was to set the pointer to a new value. However, you only copied the pointer and all changes were done to the copy.

In your Person example, you were doing bar. You had an object that was being pointed to, and you wanted to modify it. The correct way to do that is pass it by pointer (or reference).

Since you have an object you want to modify, you need to pass it by pointer (or reference). Since that object is a pointer itself, it will be a pointer to pointer.

0
On

The difference between your implementation and that of SDL2 is that in your implementation returns a pointer and the calling code assigns it to a variable.

In the SDL2 implementation, the called function wants to store the pointer, and you want it stored in an existing pointer defined by the calling code. It needs to know where to store the pointer, so it needs a pointer to the pointer.