Hi, ist es möglich in C, bei einem Funktionsaufruf die Referenz von einer Variable zu übergeben? Muss ich den Compiler dazu auf C++ umstellen, oder gibt es im C eine Spezialoption wie ich das bewerkstelligen kann? In C++ sehen die Referenzen ja ungefähr so aus: void settest(int& dst) { dst = 123; } void main(void) { int a; settest(a); } in dem normalen C Dialekt (glaube C95 oder so) hat dieses Beispiel nicht funktioniert. klar das könnte man natürlich auch mit pointern lösen: void settest(int* dst) { *dst = 123; } void main(void) { int a; settest(&a); } aber das was der compiler da herausgeneriert ist nicht schön: void settest(int* dst) { 92: fc 01 movw r30, r24 *dst = 123; 94: 8b e7 ldi r24, 0x7B ; 123 96: 90 e0 ldi r25, 0x00 ; 0 98: 91 83 std Z+1, r25 ; 0x01 9a: 80 83 st Z, r24 } 9c: 08 95 ret gibts es eine andere möglichkeit für referenzen?
Was ist denn an dem Code nicht schön? Immerhin ist er optimal so wie er übersetzt wurde. Referenzen in C++ werden intern ähnlich abgebildet: syntaktischer Zucker. Mehr nicht.
naja, eigentlich sollten ja referenzen noch besser zu behandeln sein als normal übergeben variablen, da die variablen aus der vorherigen funktion weiterbenutzt werden können und nicht erst auf dem stack gesichert werden müssen oder auf neue register umkopiert. optimal übersetzt finde ich das ehrlichgesagt nicht, der compiler könnte schon merken dass effektiv nur eine konstante speicherstelle angesteuert wird...
Stefan Noll wrote: > optimal übersetzt finde ich das ehrlichgesagt nicht, der compiler könnte > schon merken dass effektiv nur eine konstante speicherstelle angesteuert > wird... Du kannst dich ja hinsetzen und für den gcc eine entsprechende Datenflussanalyse schreiben, die draufkommt, dass deine Funktion nur ein einziges mal aufgerufen wird und daher das dst innerhalb eines Programmlaufs immer auf dieselbe Speicherstelle zeigen wird. Wie du das dann allerdings machen willst, wenn sich Funktion und Aufruf in verschiedenen Übersetzungseinheiten befinden bleibt dir überlassen. Praxisrelevant ist so eine Analyse allerdings nicht.
hmmm selbst wenn man weiß daß die Funktion (statisch) nur 1x gerufen wird brnigt das nix, weil man nicht an den Ort des referenzierten Objektes kommt. Wenn du mehr Information über die Funktion hast kannst Du dem Compiler das mitteilen, etwa wenn sie nur in einem Modul gebraucht wird (static). Vielleicht bringt das schon die Optimierung. Und hast mal den Code angeschaut, den avr-g++ für eine Referenz macht? Ich glaub nicht daß der besser ist als mit Zeigern.
versuche doch mal die Funktion als Inline zu machen. Dann sollte er es etwas besser hinbekommen. Ich kämpfe zur zeit mit ähnlichen Problemen, In C Programmieren ist zwar schön aber das was am ende Rauskommt ist leider selten optimal (was die optimierung angeht). Der Computer kann halt noch nicht denken.
> optimal übersetzt finde ich das ehrlichgesagt nicht, der compiler > könnte schon merken dass effektiv nur eine konstante speicherstelle > angesteuert wird... Das ist optimal, was der Compiler da macht. Der merkt nämlich noch viel mehr, nämlich dass der Aufruf der Funktion ohne Effekt ist, und optimiert ihn deswegen komplett weg. Die Funktion selbst muss er aber stehen lassen, weil er nicht wissen kann, ob sie vielleicht noch von einem anderen Modul aufgerufen wird. Da er dieses Modul nicht kennt, kann er auch keine Annahmen über die Variable machen, deren Adresse als Argument übergeben wird. Also ist der erzeugte Code in diesem Kontext perfekt. Wenn du möchtest, dass der Programmcode von settest ebenfalls wegoptimiert wird, musst du Johanns Vorschlag folgen und die Funktion static deklarieren, um dem Compiler anzuzeigen, dass sie nicht von anderen Modulen aufgerufen wird. Interessanteres Beispiel: Rufst du nach settest(&a) eine externe Funktion mit a als Argument auf, kann der Compiler das settest nicht komplett ignorieren, da der Wert von a ja noch benötigt wird. Aber selbst dann wird sehr stark optimiert: Der Compiler lässt den Aufruf von settest ebenfalls weg und schreibt die 123 direkt in die Argumentübergaberegister. Kurz: Der GCC optimiert nicht immer perfekt, das ist bekannt. Aber gerade in dem von dir genannte Beispiel zeigt er in beeindruckendster Weise seine Fähigkeiten. Die C++-Referenzen sind, wie Johann geschrieben hat, nur syntaktischer Zucker. Sie sind sematisch äquivalent mit konstanten Pointern, die initialisiert werden, denen aber kein Wert zugewiesen werden kann.
hi, vielen dank für den tipp mit dem als static deklarieren, erste versuche damit sehen schon ganz gut aus. ich habe kurz zwei varianten ausprobiert, void dosomethingwith(int a) { * ((int*)0) = a; } static int settest() { return 123; } void main(void) { int a; a = settest(); dosomethingwith(a); } einmal mit return und einmal mit übergebenem pointer. beide varianten hatten am ende die gleiche übersetzung und der compiler hat beides zu den einfachen 4 zeilen 9c: 8b e7 ldi r24, 0x7B ; 123 9e: 90 e0 ldi r25, 0x00 ; 0 a0: 90 93 01 00 sts 0x0001, r25 a4: 80 93 00 00 sts 0x0000, r24 wegoptimiert. also bei mit static deklarierten funktionen merkt er wohl wirklich dass es sich nur um eine speicherstelle handelt. kurz zum hintergrund: ich habe ein programm das einen quelltext generieren soll, und da wäre es unpraktisch wenn ich nochmal differenzieren müsste ob ein funktionsargument zurückgegeben werden soll oder kopiert werden soll.
> vielen dank für den tipp mit dem als static deklarieren […] der > compiler hat beides zu den einfachen 4 zeilen […] wegoptimiert. Den Funktionsaufruf wegoptimiert hätte er auch ohne das static. Das static bewirkt aber zusätzlich, dass die damit nicht mehr benötigte Funktion selbst ebenfalls weggelassen wird, was keine Rechenzeit, aber Programmspeicher spart. Deswegen ist es sinnvoll, alle Funktionen (und auch alle globalen Variablen), die nur in einem einzelnen Modul verwendet werden, als static zu deklarieren, zumal das Programm dadurch auch durchschaubarer wird.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.