4

この質問は、私からの以前の質問に基づいています。

そこに私はこの構造を持っていました。SDL2 を使用します。

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

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

これはうまくいきませんでした。答えは、*&window代わりに関数パラメーターとして使用したことを示唆しており、うまく機能しました。*&windowto**windowを次のように書き直しました。

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

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

そして、それも機能します。しかし、最初のバージョンが機能しない理由はまだわかりません。SDL_Windowの実装の詳細を調べたところ、通常typedefの名前空間に配置するのは構造体の通常の方法です。SDL_CreateWindowは を返しますSDL_Surface *.

私のジレンマを想像するために、次の簡単なプログラムを書きました。

#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);
}

これは53、ポインタからポインタへのセマンティクスを使用しなくても、期待どおりに出力されます。私の実装と SDL2 の実装の違いは何ですか。これは SDL2 の質問ではありません。以前の質問に答えた人は、SDL2 の知識がなくてもこれに答えることができたので、見逃した実装の詳細があるようです。誰かが私を啓発できることを願っています。

4

2 に答える 2

3

あなたの実装と SDL2 の実装の違いは、あなたの実装ではポインタを返し、呼び出しコードがそれを変数に代入することです。

SDL2 実装では、呼び出された関数はポインターを格納する必要があり、呼び出し元のコードで定義された既存のポインターに格納する必要があります。ポインターを格納する場所を知る必要があるため、ポインターへのポインターが必要です。

于 2016-02-21T05:58:26.667 に答える
3

説明するためのより簡単な例を次に示します。

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
}

あなたのSDLの例では、やろうとしていfooました. 目標は、ポインターを新しい値に設定することでした。ただし、ポインターをコピーしただけで、すべての変更がコピーに対して行われました。

あなたのPerson例では、あなたはやっていbarました。指し示されているオブジェクトがあり、それを変更したいと考えていました。これを行う正しい方法は、ポインター (または参照) で渡すことです。

変更したいオブジェクトがあるので、ポインター (または参照) で渡す必要があります。そのオブジェクトはポインタそのものなので、ポインタへのポインタになります。

于 2016-02-21T06:02:51.283 に答える