rvalue -> lvalue*
-
Hallo,
ist es möglich, eine Funktion oder ein Macro zu schreiben, wodurch bei einem Aufruf Speicher allokiert, ein rvalue in diesen Speicher geschrieben und die Speicheradresse zurückgegeben wird?
Also quasi etwas, was ein rvalue in einen lvalue-Pointer wandelt.Der Sinn dahinter ist, dass ich eine Funktion habe, die nur einen Pointer akzeptiert, man aber ja den Adress-Operator nicht auf rvalues anwenden kann.
pointer_function(rval_to_lval(12)); //anstatt int *tmp; tmp = malloc(sizeof(int)); *tmp = 12; pointer_function(tmp);
-
C kennt keine temporären Objekte.
-
Wenn du Extensions erlaubst, geht das recht einfach:
#define rval_to_lvalptr(i) ({typeof(i) _tmp_ = i; &_tmp_;}) void print_address(int *i) { printf("%p\n", i); } int main() { print_address(rval_to_lvalptr(10)); }
-
Mit C99:
#include <stdio.h> #define MAKE_POINTER(type, value) ((type*) &((struct{type x;}){(value)})) void foo(int *p) { printf("%d, %p\n", *p, p); } int main(void) { foo(MAKE_POINTER(int, 12)); return 0; }
-
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.
-
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.
-
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;
-
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.