Forum: Compiler & IDEs Zeiger als Rückgabewert


von hansi (Gast)


Lesenswert?

habe folgendes im buch Galileo Computing / C von A bis Z gefunden:

es geht um Zeiger als Rückgabewert:

SOLLTE Möglichkeit3 NICHT AUCH DATENMÜLL LIEFERN (gibt ja auch die 
Adresse einer lokalen Variablen zurück ) ?
1
/* ptr14.c */
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <string.h>
5
/* Fehler: Funktion gibt die Adresse
6
 * einer lokalen Variablen zurück */
7
char *test1(void){
8
   char buffer[10];
9
   strcpy(buffer, "testwert");
10
   return buffer;
11
}
12
/* Möglichkeit1: Statische Variable */
13
char *test2(void){
14
   static char buffer[10];
15
   strcpy(buffer, "testwert");
16
   return buffer;
17
}
18
/* Möglichkeit2: Speicher vom Heap verwenden */
19
char *test3(void){
20
   char *buffer = (char *) malloc(10);
21
   strcpy(buffer, "testwert");
22
   return buffer;
23
}
24
/* Möglichkeit3: Einen Zeiger als Argument übergeben */
25
char *test4(char *ptr){
26
   char buffer[10];
27
   ptr = buffer;
28
   strcpy(buffer, "testwert");
29
   return ptr;
30
}
31
int main(void) {
32
   char *ptr;
33
   ptr = test1();
34
   printf("test1: %s\n", ptr); // Datenmüll
35
   ptr = test2();
36
   printf("test2: %s\n", ptr);
37
   ptr = test3();
38
   printf("test3: %s\n", ptr);
39
   test4(ptr);
40
   printf("test4: %s\n", ptr);
41
   return EXIT_SUCCESS;
42
}

von Uhu U. (uhu)


Lesenswert?

Richtig. Beliebter Anfängerfehler...

von Karl H. (kbuchegg)


Lesenswert?

Was mich wundert:
Die vernünftigste Variante ist nicht erwähnt.

Möglichkeit 1: statische Variable.
  Das kann man machen, sollte man aber nicht ohne guten Grund
  machen. Das kann zu zunächst sehr seltsamen Effekten führen.

Möglichkeit 2: Speicher vom Heap
  Das problematische daran ist, dass der Aufrufer wissen muss,
  das der Speicher am Heap allokiert wurde und ihn wieder freigeben
  muss. Zb. im Test-main() passiert das nicht und ich werte das
  mal als bösen Fehler.

Möglichkeit 3:
  Wie du richtig erkannt hast, ist das genauso fehlerhaft, wie
  die allererste Variante

Bleibt noch Möglichkeit 4, die du am häufigsten antreffem wirst:
  Der Aufrufer muss den Speicher bereitstellen in den die Funktion
  die Daten hineinkopiert. Dabei sollte bei Arrays dann auch gleich
  noch die Grösse des Arrays mit übergeben werden, damit die Funktion
  prüfen kann, ob seine Daten in den bereitgestellten Speicherbereich
  passen.
1
char* test5(char *result, int maxLength)
2
{
3
   if( maxLength > 9 )
4
     strcpy(result, "testwert");
5
   return result;
6
}
7
8
int main(void) {
9
   char buffer[20];
10
11
   test5( buffer, sizeof(buffer) );
12
   printf("test5: %s\n", buffer);
13
14
   return EXIT_SUCCESS;
15
}

von hansi (Gast)


Lesenswert?

super danke für die richtigstellung

von yalu (Gast)


Lesenswert?

Ich schätze, Möglichkeit 3 war ursprünglich als etwas ähnliches wie
Möglichkeit 4 von Karl heinz geplant gewesen (warum hätte sie sonst
überhaupt den Parameter ptr, der in der abgedruckten Variante gar
nicht genutzt wird), ist dann aber von einem ahnungslosen Mitautor
vollständig vermurkst worden.

<Klugscheißermodus>
>    if( maxLength > 9 )
8 hätte auch genügt, wenn maxLength die Größe des Arrays ist :)
</Klugscheißermodus>

von Uhu U. (uhu)


Lesenswert?

Hoffent wischst du dir jetzt auch deinen klugen Hintern...

von Rolf Magnus (Gast)


Lesenswert?

> SOLLTE Möglichkeit3 NICHT AUCH DATENMÜLL LIEFERN (gibt ja auch die
> Adresse einer lokalen Variablen zurück ) ?

Sie SOLLTE UNDEFINIERTES VERHALTEN LIEFERN. Das kann alles mögliche 
bedeuten. Letztendlich ist diese Variante sowieso ziemlich unsinnig. Der 
übergebene Zeigerwert wird überhaupt nicht benutzt.

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.