www.mikrocontroller.net

Forum: Compiler & IDEs Zeiger als Rückgabewert


Autor: hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 ) ?
/* ptr14.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Fehler: Funktion gibt die Adresse
 * einer lokalen Variablen zurück */
char *test1(void){
   char buffer[10];
   strcpy(buffer, "testwert");
   return buffer;
}
/* Möglichkeit1: Statische Variable */
char *test2(void){
   static char buffer[10];
   strcpy(buffer, "testwert");
   return buffer;
}
/* Möglichkeit2: Speicher vom Heap verwenden */
char *test3(void){
   char *buffer = (char *) malloc(10);
   strcpy(buffer, "testwert");
   return buffer;
}
/* 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;
   ptr = test1();
   printf("test1: %s\n", ptr); // Datenmüll
   ptr = test2();
   printf("test2: %s\n", ptr);
   ptr = test3();
   printf("test3: %s\n", ptr);
   test4(ptr);
   printf("test4: %s\n", ptr);
   return EXIT_SUCCESS;
}

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Richtig. Beliebter Anfängerfehler...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.
char* test5(char *result, int maxLength)
{
   if( maxLength > 9 )
     strcpy(result, "testwert");
   return result;
}

int main(void) {
   char buffer[20];

   test5( buffer, sizeof(buffer) );
   printf("test5: %s\n", buffer);

   return EXIT_SUCCESS;
}

Autor: hansi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
super danke für die richtigstellung

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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>

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hoffent wischst du dir jetzt auch deinen klugen Hintern...

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.