Zeiger als Rückgabewert

M_Kay

Mitglied
Hi,

ich lese gerade das Buch "C von A bis Z" und bin mittlerweile beim Kapitel über Zeiger.
Leider ist das Buch an manchen Stellen nicht ganz klar formuliert, weshalb des öfteren Fragen auftreten, wovon ich eine endlich mal loswerden möchte :-)

Da das Buch online verfügbar ist, kann ich euch gleich den Link posten. Ich bin gerade hier: Klick
Eine Passage weiter unten verstehe ich nicht ganz.
Der Autor beschreibt noch einmal, dass bei einem Funktionsaufruf Daten wie lokale Variablen, Parameter etc auf dem Stack abgelegt werden. Dieser Stackframe bleibt ja nur so lange erhalten, bis die Funktion beendet wird.

Nun spricht der Autor die Problematik an, dass der Zeiger in der Funktion auf einen lokalen Speicherbereich zeigt. Wenn der Zeiger nun zurückgegeben und die Funktion beendet wird, dann geht dieser Speicherbereich ja "verloren". Der von der Funktion zurückgelieferte Zeiger würde somit auf einen "ungültigen Speicherbereich" (wenn ich das mal so nennen darf) zeigen.

Habe ich das bis hierher richtig verstanden?

Die Lösung mit dem static ist klar.
Die Lösung mit malloc wird erst später im Buch besprochen.

Bleibt noch die letzte Möglichkeit das Problem zu beseitigen:
Der Funktion wird ein Puffer/Zeiger übergeben.
Und hier endet meine Vorstellungskraft :D Denn in dem Code-Beispiel wird dem übergebenen Zeiger ja trotzdem wieder die Adresse eines lokalen Speicherbereichs übergeben, oder? Aber warum funktioniert das dann auf einmal?

Gruss
M_Kay
 
Hi,

ha mir den Link zwar nicht angeschaut, aber das Problem/die Frage ist auch so recht klar

Angenommen, du bist im main und rufst eine Funktion a auf.
Das main hat eine int i, die in der Funktion geändert (oder so) werden soll
Du übergibst also die Adresse von i, und am Beginn von a wird der Stackbereich davon angelegt.

Da du jetzt aber auf eine Var vom Main-Stack zugreifen willst, verstehst du nicht, wieso das geht, weil der mainstack ja weg ist?

Eben nicht :-)
Der mainstack wird erst dann abgebaut, wenn main zu Ende ist.
Während a läuft, befindet sich das main ja in so einer Art "Wartezustand", es wird NICHT beendet und alle Variablen im main existieren auch weiterhin, solange bis die Funktion main aus ist-
und das muss ja dann zwangsläufig nach dem Ende von a sein.

Gruß
 
Ja, das ist klar. Aber auf der Seite ist das Beispiel anders:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
...
/* Möglichkeit3: Einen Zeiger als Argument übergeben */
char *test4(char *ptr){
   char buffer[10];
   ptr = buffer;
   strcpy(buffer, "testwert");
   return ptr;
}
int main(void) {
   char *ptr;
   test4(ptr);
   printf("test4: %s\n", ptr);
   return EXIT_SUCCESS;
}
Hier ist der Zeiger in der main definiert und wird an die Funktion test4 übergeben.
In dieser test-Funktion wird der Zeiger auf einen lokalen Speicherbereich (buffer) gepointet und zurückgegeben.

Ich greife nach dem Funktionsaufruf doch also mit dem Pointer auf einen lokalen Speicherbereich der Funktion test4 zu, oder? Und ich dachte das geht eben nicht, weil nach dem Beenden der Funktion der Stackframe freigegeben wird.
 
Es geht ja auch nicht, hast du den Code mal getestet?
Auf der Cmd hast du dann da stehen: "test4: (null)"
 
Hm, in der Tat gibt er bei dem von mir geposteten gekürztem Beispiel nur Datenmüll aus.
Nutze ich jedoch das komplette Beispiel von der Seite, dann gibt er "test4: testwert" aus. Ist das jetzt nur Zufall, dass der Zeiger auf den richtigen Wert zeigt?

Wenn ja, dann ist das was im Buch steht ja völlig falsch?!
 
Jedenfalls Methode 4 ist daneben...probier einmal aus, bei jeder der 4 funks andere
Strings reinzuschreiben, so wie testwer1, testwer2
Ausgabe müsste dann lauten
testwer1
testwer2
testwer3
testwer4

beim letzten kommt aber auch testwer3 raus

Das da zufällig was sinnvolles kommt, ist wirklich nur Zufall
 
Ich habe jetzt mal den gesammten Code genommen, nur dass ich mir nicht Testwert, sondern Test1 - Test4 habe ausgeben lassen, auf meiner Console sah das dann so aus:

test1: (MÜLL);
test2: test2
test3: test3
test4: test3;

das verwirrt mich jetzt zugegebener Maßen doch.
Ich hätte erwartet, dass hinter test4 irgend ein Müll steht, aber vielleicht ist der Compiler gnädig und setzt das irgendwie zurück.... :confused:
 
jedenfalls kommt nicht das richtige raus->Fehler
Ich vermute, da schlägt die Optimierung zu - Gnadenlos Bytes und Variablen einsparen, wo es nur geht

Edit: Ich weiss ja nicht, was ihr zwei für Compiler verwendet, aber bei mir ändert sich die Ausgabe wirklich,
wenn ich die Optimierungen ausschalte.
Edit2: Das War Unsinn, es ändert sich nur der Datenmüll vom 1., hier gehts ja ums 4.
 
Zuletzt bearbeitet:
Ok, also kann ich davon ausgehen, dass das ein Fehler im Buch ist? Denn das ist ja keineswegs eine Lösung für das genannte Problem :D

Das ist nicht der erste Fehler in dem Buch, den ich finde.... vllt sollte ich das Buch wechseln ...
Wenigstens lernt man ja auch was dabei, wenn man die Fehler selbst findet :D

Also ist es vermutlich im Buch so gemeint gewesen wie von sheel im 2. posting genannt. Also das man den Puffer in der main definiert und einen Zeiger auf diesen an die Funktion übergibt, oder?
 
Zurück