mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Rückgabewert


Autor: Kristina (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
hab schon lange nichts mehr mit C gemacht und stoße jetzt auf das
Problem mir einen Rückgabewert richtig zurückgeben zu lassen. Hier das
Beispiel:

--------------------------------------------------------------
/* prototype */
unsigned char func1(void);

/* Func1 */
unsigned char func1(void){
  unsigned char xyz[10];
  strcpy(xyz,'test1\0');
  return xyz;
}

/* main */
int main(void)
{
  unsigned char abc[10];

  abc = func1();

  lcd_init(LCD_DISP_ON_CURSOR_BLINK);
  lcd_puts(abc);
}
--------------------------------------------------------------

Wie gebe ich den Wert in xyz richtig zurück ? Über Pointer ?

Bitte die Antwort so ausführlich wie möglich, damit ich den Sachverhalt
einmal für immer verstehe.

Gruß

Autor: Rufus T. Firefly (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
unsigned char func1(void){
  unsigned char xyz[10];
  strcpy(xyz,'test1\0');
  return xyz;
}

Hier treten mehrere Probleme auf:

a) Stringkonstanten sind in Anführungszeichen (") einzuschließen,
nicht in Hochkommata ('), die sind für Zeichenkonstanten da.

b) Der Rückgabewert soll ein char sein, zurückgegeben wird aber ein
char*.

c) Die Variable xyz ist eine automatische Variable, die auf dem Stack
angelegt wird.
Der zurückgegebene Pointer verweist somit auf Speicher, der nach dem
Beenden der Funktion nicht mehr gültig ist.

Damit ein Pointer auf diese Variable zurückgegeben werden kann, muss
entweder die Variable als static deklariert werden - damit ist sie
nicht mehr automatisch, sondern einmalig im .Text-Segment angelegt.

Das ist sehr ungeschickt, weil bei aufeinanderfolgenden Aufrufen der
Funktion die Variable jeweils überschrieben wird.

Eine Alternative wäre es, die Variable dynamisch via malloc
anzufordern, dann muss aber der Aufrufer der Funktion nach Gebrauch des
Ergebnisses dafür sorgen, daß der Speicher mit free zurückgegeben wird.
Das wird gerne vergessen und ist auch aus anderen Gründen eine
potentielle Fehlerquelle.

Hier ist eine völlig andere Vorgehensweise sinnvoller:


/* Func1 */
void func1(char* pString){
  strcpy(pString, "test1");
}

/* main */
int main(void)
{
  unsigned char abc[10];

  func1(abc);

  lcd_init(LCD_DISP_ON_CURSOR_BLINK);
  lcd_puts(abc);
}

Der Funktion wird ein Pointer auf den zu beschreibenden Speicher
übergeben, der Speicher wird in main von der Variablen abc zur
Verfügung gestellt.
Die terminierende Null in der Stringkonstante wird von strcpy eh'
hinzugefügt und muss daher nicht explizit geschrieben werden, außderdem
wird sie auch implizit zur Stringskontanten selbst hinzugefügt.

Hier gibt es noch einige potentielle Fehlerquellen:

func1 überprüft nicht das übergebene Argument auf Gültigkeit. Wird NULL
beim Aufruf übergeben, interessieren spannende Dinge.

Desweiteren weiß func1 nicht, wie groß der Speicherbereich ist, auf den
der übergebene Pointer verweist. Wird in main die Größe von abc auf
weniger als 6 Zeichen (Länge von "test1" plus terminierende Null)
reduziert, überschreibt der strcpy-Aufruf in func nicht reservierten
Speicher.

Daher ist es sinnvoll, der Funktion func1 die Länge des Stringpuffers
zu übergeben und diese auch auszuwerten:




/* Func1 */
void func1(char* pString, int Laenge){
  strncpy(pString, Laenge, "test1");
}

/* main */
int main(void)
{
  unsigned char abc[10];

  func1(abc, 10);

  lcd_init(LCD_DISP_ON_CURSOR_BLINK);
  lcd_puts(abc);
}


Uuuund jetzt folgt mein beliebter Hinweis, auf den hier vermutlich
schon alle anderen gierigst gewartet haben:

Mehr zum Thema kann man im Buch "Programmieren in C" von Kernighan &
Ritchie, zweite Auflage, Hanser Verlag nachlesen.

Autor: Kristina (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, hab's auch nachgelesen ;)

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.