Datentyp aus Funktion direkt als Datentyp* (Pointer) übergeben



  • schlauch schrieb:

    Dynamisch machen wollte ich verhindern, aber danke kannte den Weg über mfree nicht.

    Der Rückgabewert soll auch kein Pointer sein, sondern ein Wert bleiben =/.

    Wenn es am toten Resultat liegen sollte, sollte es doch mit static am Leben bleiben(?):

    struct MyStruct createMyStruct()
    {
      static struct MyStruct myStruct;
      myStruct.i = 0;
      return myStruct;
    }
    

    geht aber mit gleicher Fehlermeldung auch nicht 😕
    stehe wohl immernoch auf dem Schlauch

    Jetzt könnte aber ein Pointer als Rückgabewert funktionieren:

    struct MyStruct* createMyStruct()
    {
      static struct MyStruct myStruct;
      myStruct.i = 0;
      return &myStruct;
    }
    


  • _matze schrieb:

    Was du da versuchst, könnte sogar kompilieren und 'funktionieren', aber das struct hört mit dem Ausführungsende von api_foo auf zu existieren, so dass es letztlich unsinnig ist.

    jein, das lokale objekt existiert zwar nicht mehr, aber es wird eine kopie erstellt, wenn der rückgabewert benutzt wird (daher auch nur für kleine structs sinnvoll):

    struct MyStruct createMyStruct()
    {
      struct MyStruct m;
      m.i = 0xcafebabe;
      return m;
    }
    
    void main (void)
    {
       // funzt
       struct MyStruct m = createMyStruct();
       printf ("%08x\n", m.i);
       // funzt auch
       printf ("%08x\n", createMyStruct().i);
    }
    

    🙂



  • fricky, was du schreibst, ist schon klar. Aber es ging darum, dass ein Zeiger auf diesen Rückgabewert an api_foo übergeben und er dort verändert wird. Und wenn api_foo endet, gibt's auch das struct, auf das gezeigt wurde, nicht mehr. Also ist diese Übergabe und die Benutzung des Zeigers unsinnig, weil man sowieso nie mehr an die Daten rankommt, die man da so schön editiert hat (sieh dir den zuerst geposteten Code an).



  • _matze schrieb:

    ...

    oh sorry, der vorschlag mit 'malloc' war ja garnicht von dir. hab das gedanklich beim überfliegen des threads irgendwie vermischt.
    🙂



  • Ja das erste Beispiel zeigt eigentlich nicht was die Apifunktion tut - kann ich jetzt leider nicht mehr editieren 😕

    Das Problem hat aber soweit ich das sehe bis jetzt noch niemand beantwortet warum 1. geht und 2. nicht 😕

    // 1.
    struct MyStruct myStruct = createMyStruct(); 
    api_foo(&myStruct);
    // 2.
    api_foo(&createMyStruct());
    

    macht für mich einfach keinen Sinn bis jetzt 😕



  • schlauch schrieb:

    Ja das erste Beispiel zeigt eigentlich nicht was die Apifunktion tut - kann ich jetzt leider nicht mehr editieren 😕

    Das Problem hat aber soweit ich das sehe bis jetzt noch niemand beantwortet warum 1. geht und 2. nicht 😕

    // 1.
    struct MyStruct myStruct = createMyStruct(); 
    api_foo(&myStruct);
    // 2.
    api_foo(&createMyStruct());
    

    macht für mich einfach keinen Sinn bis jetzt 😕

    da fehlt dir ein sogenannter 'lvalue', das ist ein objekt, das im speicher vorhanden ist (z.b. ist alles 'lvalue', was ziel einer zuweisung sein kann, steht auf der linken seite davon). rückgabewerte von funktionen sind immer 'rvalues', d.h. du kannst die irgendwas zuweisen, aber nicht die adresse davon nehmen. beispiel:

    int a = 1; // a ist lvalue (hat 'ne adresse), 1 ist rvalue (hat keine adresse)
    ...
    int *a = &1;  // geht nicht, ein literal hat keine adresse
    
    ...
    
    int f(void) {return 1;};
    ...
    int *a = &f();  // geht nicht, ein rückgabewert hat keine adresse
    ...
    int i = f();
    int *a = &i;    // aber so gehts, also rückgabewert einem realen objekt zuweisen und dann die adresse davon nehmen
    

    🙂



  • Danke für die Erklärung - so macht das ein ganzes Stück mehr Sinn 🙂

    Dachte beim Funktionsrückgabewert würde ich auch ein "anonymes Objekt" bekommen auf dem ich wenigstens arbeiten könnte wie mit einer lokalen Variablen - dem ist wohl leider nicht so.
    Bleibt mir wohl nur die Lösung über static struct in der createMyStruct ein einen Pointer als Rückgabewert.
    Werd wohl noch ein bisschen dran grübeln.

    Danke an alle 🙂



  • Warum sträubst du dich eigentlich so, eine Variable zu dem Zweck anzulegen? Ist doch nix Schlimmes dabei. Eine Zeile mehr, was soll's...



  • schlauch schrieb:

    Dachte beim Funktionsrückgabewert würde ich auch ein "anonymes Objekt" bekommen auf dem ich wenigstens arbeiten könnte wie mit einer lokalen Variablen - dem ist wohl leider nicht so.

    bekommste ja auch, aber es hat keine adresse. sowas z.b. geht:

    printf ("%d\n", createMyStruct().i);  // auf member des 'virtuellen objekts' zugreifen
    

    rückgewerte haben keine adressen, weil sie sich zu dem zeitpunkt z.b. noch in irgendwelchen prozessorregisten befinden könnten.

    schlauch schrieb:

    Bleibt mir wohl nur die Lösung über static struct in der createMyStruct ein einen Pointer als Rückgabewert.

    ne, das wär sogar äusserst doof, weil jeder aufruf von 'createMyStruct' immer dasselbe objekt liefern würde. zumindest der name der funktion wäre dann ziemlich irreführend.
    🙂



  • _matze schrieb:

    Warum sträubst du dich eigentlich so, eine Variable zu dem Zweck anzulegen? Ist doch nix Schlimmes dabei. Eine Zeile mehr, was soll's...

    Müsste die API-Funktion von vielen verschiedenen Stellen im Code aufrufen - und da wäre es sehr unschön jedesmal eine Hilfsstruktur pro Funktionsaufruf zu erstellen beziehungsweise aufzufüllen - dachte mit einer Hilfsfunktion die das für mich erledigt wär es einfacher und sauberer 🙂

    ;fricky schrieb:

    schlauch schrieb:

    Bleibt mir wohl nur die Lösung über static struct in der createMyStruct ein einen Pointer als Rückgabewert.

    ne, das wär sogar äusserst doof, weil jeder aufruf von 'createMyStruct' immer dasselbe objekt liefern würde. zumindest der name der funktion wäre dann ziemlich irreführend.
    🙂

    Das stimmt wohl - die Funktion ist aber nur dazu gedacht eine für die API-Funktion neu befüllte Struktur zu erzeugen. Sie wird eigentlich nur beim Aufruf dieser API-Funktion verwendet und die static struct kann in sofern nicht versehentlich mit falschen Werten neu erzeugt und damit überschrieben werden.
    Über den Namen mach ich mir aber besser nochmal Gedanken 🙂



  • schlauch schrieb:

    die Funktion ist aber nur dazu gedacht eine für die API-Funktion neu befüllte Struktur zu erzeugen. Sie wird eigentlich nur beim Aufruf dieser API-Funktion verwendet und die static struct kann in sofern nicht versehentlich mit falschen Werten neu erzeugt und damit überschrieben werden.

    Die Aufrufe der API-Funktion können sich aber nicht überschneiden (Threads), ja?



  • schlauch schrieb:

    Das stimmt wohl - die Funktion ist aber nur dazu gedacht eine für die API-Funktion neu befüllte Struktur zu erzeugen. Sie wird eigentlich nur beim Aufruf dieser API-Funktion verwendet und die static struct kann in sofern nicht versehentlich mit falschen Werten neu erzeugt und damit überschrieben werden.

    mach doch sowas:

    // MyStruct initialisieren
    void setup (struct MyStruct *s)
    {
     s.i = ...;
     ...
    }
    ...
    // in zwei schritten eine neue struct anlegen
    struct MyStruct s;
    setup (&s);
    ...
    

    ^^so erhältste jedesmal eine neue struct wo du sie brauchst.
    wenn am anfang alles 0 sein soll, kannste dir sogar 'ne eigene init-funktion sparen und machst es einfach so:

    struct MyStruct s;
    memset (&s, 0, sizeof(s));
    

    🙂


Anmelden zum Antworten