Zeiger als Rückgabewert

Gast #647095
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
}
#647106
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
}
Gast #647138
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>
Gast #647222
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren