Forum: PC-Programmierung Zeiger als Rückgabetyp einer Funktion oder als Parameter?


von Tobi (Gast)


Lesenswert?

Moin,

ich habe ene Frage zu zeigern in C/C++. Macht es einen Unterschied, ob 
ich für eine Struktur oder ein anderes großes Objekt eine der folgenden 
beiden Methoden verwende: Zeiger als Funktionsparameter oder Zeiger als 
Rückgabetyp einer Funktion?

Für beide muss ich mir in der main() eine Instanz erstellen. Ob ich nun 
die Anfangsadresse dieser Strukturinstanz als Parameter an eine Funktion 
übergebe oder aber einen Zeiger als Rückgabetyp einer Funktion nehme, 
spielt doch keine Rolle oder gibt es da Unterschiede? Zeiger als 
Parameter einer Funktion dienen ja in erster Linie dazu, dass man nicht 
lokal an Funktionsvariablen gebunden ist und mehr als einen Rückgabewert 
hat. Aber Zeiger als Funktionsparameter sind auch praktisch, wenn man 
eben die Adresse eine Struktur übergibt und dann mittels Zeiger die 
Strukturelemente ändern kann. Also wozu dann Zeiger als Rückgabetyp 
einer Funktion?

von ui (Gast)


Lesenswert?

Du kannst dann z.B. in der Funktion auf dem Heap eine Instanz von einem 
Objekt erstellen und die Addresse davon zurückgeben. Es gibt da immer 
mehrere Möglichkeiten für das gleiche Problem. Oder man möchte die 
Funktion so bauen, dass das Ursprungsobjekt prinzipiell nicht geändert 
wird (const), aber trotzdem die Möglichkeit haben ein neues Objekt 
gleichen Types mit veränderten Einstellungen zurückzugeben.
Ich persönlich finde Zeiger als Rückgabewert von einer Funktion nicht 
soo schön, auch wenn ich es schon einige Male genutzt habe.

Es ist aber vom prinzip her etwas ganz anderes!

von Sven B. (scummos)


Lesenswert?

Pointer als Rückgabetypen sollten genau dann verwendet werden wenn die 
Funktion die Adresse eines bereits existierenden Objekts an den 
Aufrufenden zurückgeben soll, weil der irgendwas damit machen will. Wenn 
du den Speicher für das Objekt in der Funktion erst reservierst, gibt 
man besser einen shared / uniqe pointer zurück.

von Tobi (Gast)


Lesenswert?

Bei Parameter Übergabe kann ich in der Main die Instanz der Struktur 
auch ändern. Auch ohne Zeiger als Rückgabe typ.

von Marc (Gast)


Lesenswert?

Irgendwie bin ich zu böd die Frage bzw. die Antworten zu verstehen...

Wenn man einen Zeiger auf ein Objekt/Struktur aus einer Funktion 
zurückgeben möchte, dann kann man entweder den Zeiger als return Wert 
zurückgeben oder einen Zeiger auf einen Zeiger als Pameter nutzen.
(Referenzen mal unbetrachtet...)

Der feine Unterschied

* "ich teile der Funktion mit, wo das Objekt liegt" (Parameter Zeiger 
auf Objekt) und der Variante

* "ich teile der Funktion mit, wo sie mir ihren Zeiger auf das Objekt 
zurückliefern kann" (Parameter Zeiger auf Zeigerauf Objekt)
fehlt mir hier.

von Tobi (Gast)


Lesenswert?

Irgendwie hilft mir das nicht weiter. Ob Zeiger als Rückgabetyp oder 
Zeiger als Parameter,am Ende landet das Ergebnis trotzdem in der 
MainFunktion. Wo also liegt ein Unterschied?

von Mitlesa (Gast)


Lesenswert?

Tobi schrieb:
> Wo also liegt ein Unterschied?

Beim Pointer auf eine Struktur bekommst du genau einen Pointer
umkopiert, bei der Übergabe einer Struktur wird eine grössere
Datenmenge (entsprechend der Grösse der Struktur) umkopiert.
Bei zeitkritischen Dingen also ein Thema.

Ist es das was du wissen woltest?

von Hmmm (Gast)


Lesenswert?

Mitlesa schrieb:
> Beim Pointer auf eine Struktur bekommst du genau einen Pointer
> umkopiert, bei der Übergabe einer Struktur wird eine grössere
> Datenmenge (entsprechend der Grösse der Struktur) umkopiert.
> Bei zeitkritischen Dingen also ein Thema.
>
> Ist es das was du wissen woltest?

Ich glaube, dass er
- Zeiger auf Zeiger als Parameter
und
-Zeiger als Rückgabewert
meint.
So ganz verstehe ich seine Frage aber auch nicht.

@Tobi

"Aber Zeiger als Funktionsparameter sind auch praktisch, wenn man
eben die Adresse eine Struktur übergibt und dann mittels Zeiger die
Strukturelemente ändern kann. Also wozu dann Zeiger als Rückgabetyp
einer Funktion?"

Mir ist nicht ganz klar, wie die beiden Sätze logisch zusammenhängen 
("Also wozu ..."). Das eine ist die Übergabe eines Zeigers (Effizienz), 
das andere die Rückgabe eines Ergebnisses (z.B. Zeiger, wenn in der 
Funktion Speicher allokiert wurde). Es gibt Funktionen, die den 
übergebenen Zeiger wieder zurückgeben, weil der aufrufende Code dann 
u.U. eleganter geschrieben werden kann, aber ich denke nicht, dass du 
das meinst.

von Mickael (Gast)


Lesenswert?

Tobi schrieb:
> Irgendwie hilft mir das nicht weiter. Ob Zeiger als Rückgabetyp
> oder
> Zeiger als Parameter,am Ende landet das Ergebnis trotzdem in der
> MainFunktion. Wo also liegt ein Unterschied?

Das hängt von dir ab und was du machen willst.

Schau dir die beiden Funktionen printf() und strcpy() an. ?

von Timm R. (Firma: privatfrickler.de) (treinisch)


Lesenswert?

Hallo Tobi,

ich glaube mittlerweile habe ich die Frage verstanden. Alles was zur 
Antwort gehört wurde hier schon gepostet, vielleicht würde es Dir 
helfen, wenn ich es noch mal zusammenfasse.

Ich gehen mal davon aus, dass es um C geht und es nur die beiden Fälle 
1. Pointer übergeben, aber keinen liefern und 2. Pointer liefern aber 
keinen übernehmen. Von Zeigern auf Zeiger steht in Deiner Frage nichts, 
den Fall schließe ich auch aus. Ferner schließe ich den Zugriff auf den 
globalen Scope aus.

Pointer wird übergeben

möglich:
• In die Struktur, auf die der Pointer zeigt schreiben
• Aus der Struktur, auf die der Pointer zeigt lessen
• mehrfacher Aufruf mit der selben Struktur (akkumulieren)

Die Funktion kann zum Beispiel ein Member der Struktur erhöhen.

nicht möglich:
• Neue Struktur erzeugen und zurückgeben
• Zerstörungsfreie Rückgabe der Struktur

Die Funktion kann zum Beispiel nichts zurückgeben ohne die Struktur, auf 
die der Pointer zeigt, zu verändern.

Pointer wird zurückgegeben

zwingend erforderlich
• Es muss ein neuer Speicherbereich allokiert werden

nicht möglich:
• mehrfacher Aufruf mit der selben Struktur
• mehrfacher Aufruf, ohne dass Speicher allokiert wird
• Zugriff auf bestehende Daten in einer Struktur

ohne Anspruch auf Vollständigkeit :-)

vlg

Timm

: Bearbeitet durch User
von Noch einer (Gast)


Lesenswert?

Ein Beispiel wäre:

FILE* fopen(const char *filename, const char *mode);
int fprintf(FILE *stream, const char *format, ... );
int fclose (FILE *stream);

fopen() allokiert einen Speicherbereich und liefert einen Zeiger zurück.
fprintf() und fclose() bekommen diesen Zeiger als Parameter. Verändern 
über den Zeiger die Daten.

Heutzutage schreibt man const char *format, damit jeder sofort sieht, 
fprintf() verändert nur *stream, nicht aber *format.

von Tobi (Gast)


Lesenswert?

Besten Dank für die Infos. Denke ich habe es verstanden. Eine kurze 
Frage noch.

Was ist vorteilhafter:
1
int i = 5;
2
int *ptr = &i;

Oder direkt
1
int *ptr;
2
*ptr = 5;

Der Wert steht so oder so an einer Adresse, egal ob diese einen Namen 
hat wie "i" oder wo liegt der Unterschied?

von Sven B. (scummos)


Lesenswert?

Der Unterschied ist dass das zweite abstürzt weil der Pointer 
uninitialisiert ist und auf keinen reservierten Speicher zeigt. Das geht 
so nicht.

Beitrag #5073663 wurde von einem Moderator gelöscht.
von Peter (Gast)


Lesenswert?

Dein zweites Beispiel würde funktionieren, wenn Du den Zeiger vorher auf 
eine Variable zeigen lässt:
1
int i;
2
int *ptr = &i;
3
*ptr = 5;
4
5
printf("%d", i);

Ergibt:
1
5

von Rolf M. (rmagnus)


Lesenswert?

Tobi schrieb:
> Besten Dank für die Infos. Denke ich habe es verstanden. Eine kurze
> Frage noch.
>
> Was ist vorteilhafter:
> int i = 5;
> int *ptr = &i;
>
> Oder direkt
> int *ptr;
> *ptr = 5;
>
> Der Wert steht so oder so an einer Adresse,

"An einer Adresse" reicht aber nicht. Er muss schon auch an der Adresse 
stehen, wo er hingehört.

> egal ob diese einen Namen hat wie "i" oder wo liegt der Unterschied?

Im ersten Fall wird eine Variable angelegt, der offiziell der Speicher 
zugeordnet ist. Dann holst du dir die Adresse dieser Speicherstelle und 
schreibst da eine 5 rein.
Im zweiten Fall hast du einen Zeiger, der uninitialisiert ist, also 
irgendwo in den Speicher auf eine mehr oder weniger zufällige Adresse 
verweist. Danach nimmst du diesen und schreibst damit deine 5 irgendwo 
"ins Gemüse". Nach ISO C ist das Verhalten dieser Zeile undefiniert, da 
man uninitialisierte Zeiger nicht dereferenzieren darf.

von Mickael (Gast)


Lesenswert?


von Peter D. (peda)


Lesenswert?

Pointer als Returnwert nimmt man vorzugsweise für Stringfunktionen.
Z.B. gibt jeder Aufruf von strtok() den Pointer auf das nächste Token 
zurück.

von Mickael (Gast)


Lesenswert?

Peter D. schrieb:
> Pointer als Returnwert nimmt man vorzugsweise

Wenn man einen Zeiger zurück geben mochte. :-P

Das macht hauptsächlich Sinn, wenn es sich um größere Datenmengen 
handelt, die direkt weiterverarbeitet werden. z. B. als Parameter.

Bei Strings passen die Bedingungen auch und wer mit mehrschichtiger 
Kommunikation zu tun hat,weiss Bescheid.

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
Noch kein Account? Hier anmelden.