4

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.

Community
  • 1
  • 1
hgiesel
  • 5,430
  • 2
  • 29
  • 56
  • choose a language tag, C and C++ are different. (Your last program is invalid in C++) – M.M Feb 21 '16 at 11:08
  • `auto init_window(SDL_Window **window)` is illegal in C++ (before C++17 anyway!) and C. Your compiler should comment on this. Maybe you meant to return `void` ; or follow the model you used in your test program and have `SDL_Window *init_window(void)` – M.M Feb 21 '16 at 11:10
  • I can see how the first two are invalid in C (`auto` return type doesn't exist in C) and how the third one is invalid in C++ (the `malloc`), but I wonder why the first two are also supposed to be invalid in C++? – hgiesel Feb 21 '16 at 15:07
  • `auto` return type deduction for free functions was not added until C++17 – M.M Feb 21 '16 at 19:28

2 Answers2

3

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.

Michael Greene
  • 10,343
  • 1
  • 41
  • 43
3

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.

Weak to Enuma Elish
  • 4,622
  • 3
  • 24
  • 36