rvalue -> lvalue*



  • Nachtrag: Sauberer:

    #define MAKE_POINTER(type, value) (&((struct{type x;}){(value)}).x)
    


  • @camper: Wie meinst du das?

    @ würstli: Dein Macro erzeugt den gleichen Fehler
    Fehler: Als Operand für unäres »&« wird L-Wert erfordert

    @ seldon: Das funktioniert, vielen Dank 🙂
    Was machen denn die {}-Klammern um value bzw. wieso sind die nötig, damit es fehlerfrei kompiliert?



  • Damit wird ein unbennantes, temporäres Objekt einer nicht näher benannten Struktur erzeugt und die Adresse des Members x zurückgeliefiert.
    Damit x den Wert value hat, muss die Initialisierungsliste aufgerufen werden.
    Voll ausgeschrieben wäre das Konstrukt:

    struct foo
    {
        type x;
    };
    
    struct foo f{value};
    &f.x;
    

    , wenn ich mich nicht irre.



  • Es handelt sich um ein compound literal.



  • Alles klar, danke sehr.


  • Mod

    Wurstinator schrieb:

    @camper: Wie meinst du das?

    Das es ein bisschen zu spät war, um vernünftig zu antworten :p

    Im Vergleich zu temporären Objekten in C++ leben diese compound literale länger: bis zum Ende des Blocks, als ob sie als lokale Variablen deklariert worden wären.



  • camper schrieb:

    C kennt keine temporären Objekte.

    Dann lies mal im C11 Standard-Draft nach. Da sind sie nämlich definiert als Objekte mit "temporary lifetime" bei struct/union mit Array-Elementen.


  • Mod

    Wutz schrieb:

    camper schrieb:

    C kennt keine temporären Objekte.

    Dann lies mal im C11 Standard-Draft nach. Da sind sie nämlich definiert als Objekte mit "temporary lifetime" bei struct/union mit Array-Elementen.

    Danke für den Hinweis.
    Das bedeutet im Prinzip, dass ein C11-Compiler in bestimmten Fällen kopieren muss, wo das zuvor nicht erforderlich war.



  • Ja, aber nur bei dort titulierten "non-lvalues", also z.B. bei struct als Funktionsrückgabe in der Form:

    struct bla { int x[100]; };
    struct bla f() {...}
    und dann
    int *x = f().x;
    

  • Mod

    Wutz schrieb:

    Ja, aber nur bei dort titulierten "non-lvalues", also z.B. bei struct als Funktionsrückgabe in der Form:

    struct bla { int x[100]; };
    struct bla f() {...}
    und dann
    int *x = f().x;
    

    Schon klar. Wobei der Zeiger nat. noch im selben Ausdruck konsumiert werden müsste.
    Die Tatsache, dass C bei Rückgabe einer Struktur keine Kopie anlegen muss, ist imo eine der wenigen Punkte, in denen C gegenüber C++ einen Vorteil hat.
    Von der Entwicklung her sieht es ja so aus:
    C89: die Umwandlung in Zeiger ist nur für lvalue-Arrays möglich
    C99: Zeigerumwandlung möglich, aber es bleibt unspezifiert, ob das Array eine andere Identität als alle anderen Arrays des Programmes hat.
    C11: die Frage wäre geklärt.


Anmelden zum Antworten