www.mikrocontroller.net

Forum: Compiler & IDEs String innerhalb und ausserhaln von Funktionen


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe eine ganz dumme und simple Frage. Ich habe einen pointer auf 
ein char array in c in einer funktion und alles ist fein. die Pointer 
hole ich mir als teil einer referenzierten Struktur in mein Hauptprogram 
und dort zeigt der pointer ins nichts.
Wie kann ich das lösen und was muss ich am Ende frei geben?

typedef struct{
  int av;
  int an;
  char *p_vor;
  char *p_nach;
  char vor[4];
  char nach[7];
}V_N_Name;

void expandString3(V_N_Name *innen){
  char vorn[] = {"Gabi"};
  char nachn[] = {"Blaubeere"};
  innen->an = 7;
  innen->av = 4;
  innen->p_vor = &vorn[0];
  printf("expand String3: Vorname ist %s\n", innen->p_vor);
  innen->p_nach = &nachn[0];
  printf("expand String3: Nachname ist %s\n", innen->p_nach);
}
  expandString3(&aussen);
  printf("Der vollständige Name meiner lieben Frau ist: %s 
s\n",aussen.p_vor, aussen.p_nach);


Ergebnis:
expand String3: Vorname ist Gabi
expand String3: Nachname ist Blaubeere
Der vollständige Name meiner lieben Frau ist:  !@

Mein 2ter Ansatz war:

void expandString2(V_N_Name *innen){
  innen->an = 7;
  innen->av = 4;
  printf("expandString2: Vorname: %s\n", innen->vor);
  strcat(innen->vor,"Gabi");
  printf("expandString2: Vorname: %s\n", innen->vor);
  strcat(innen->nach,"Blaubeere");
  printf("expandString2: Vorname: %s\n", innen->vor);
  printf("expandString2: Nachname: %s\n", innen->nach);
  }

  expandString2(&aussen);
  printf("Der vollständige Name meiner frau ist: %s %s\n",aussen.vor, 
aussen.nach);
  printf("Vorname: %s\n", aussen.vor);
  printf("Nachname: %s\n", aussen.nach);

Ergebnis:
expandString2: Vorname:
expandString2: Vorname: Gabi
expandString2: Vorname: GabiBlaubeere
expandString2: Nachname: Blaubeere
Der vollständige Name meiner frau ist: GabiBlaubeere Blaubeere


Was mache ich in den Beispielen falsch? Vielen Dank für Eure Hilfe.
/Pepe

Autor: moep (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

die Strings vorn und nachn leben auf dem Stack. D.h.
sie sind lokal in deiner Funktion expandString3 und werden
gelöscht, wenn die Funktion zurückkehrt.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der erste Fehler ist, daß deine Programme unvollständig sind (wo ist 
aussen definiert?).

Der zweite ist, daß sie unformatiert sind und schlecht zu entziffern.

Der dritte, daß im zweiten Fall für Vor- und Nachname nirgends Speicher 
beschafft wird (worauf zeigt innen-Yvor ?). => C-Grundlagen!

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
moep schrieb:
> Hallo Peter,
>
> die Strings vorn und nachn leben auf dem Stack. D.h.
> sie sind lokal in deiner Funktion expandString3 und werden
> gelöscht, wenn die Funktion zurückkehrt.

ja, auch das noch.

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void expandString3(V_N_Name *innen){
  char vorn[] = {"Gabi"};        <============ nur zur Laufzeit von
  char nachn[] = {"Blaubeere"};  <============ expandString3 gültig!
  innen->an = 7;
  innen->av = 4;
  innen->p_vor = &vorn[0];

Besser

void expandString3(V_N_Name *innen){
  static char vorn[] = {"Gabi"};
  static char nachn[] = {"Blaubeere"};
  innen->an = 7;
  innen->av = 4;
  innen->p_vor = &vorn[0];

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, als erstes ich habe nur teile raus kopiert.
In der Main ist aussen schon deklariert.

  V_N_Name aussen;

Die Software baut ja auch.

"Hallo Peter,

die Strings vorn und nachn leben auf dem Stack. D.h.
sie sind lokal in deiner Funktion expandString3 und werden
gelöscht, wenn die Funktion zurückkehrt."

Das habe ich mir gedacht. Kann ich die Info auf diese Weise aus der 
Unterroutine irgendwie raus bekommen?

  printf("expandString2: Vorname: %s\n", innen->vor);
  //sollte leer sein
  strcat(innen->vor,"Gabi");
  printf("expandString2: Vorname: %s\n", innen->vor);
  //ich erwarte Gabi und bekomme es auch
  strcat(innen->nach,"Blaubeere");
  printf("expandString2: Vorname: %s\n", innen->vor);
  //ich erwarte Gabi, bekomme aber gabi blaubeere warum
  printf("expandString2: Nachname: %s\n", innen->nach);
  //ich erwarte Blaubeere und bekomme es auch.

Aber warum bekomme ich einmal Gabi Blaubeere statt gabi?

Beitrag melden | Bearbeiten | Löschen |

Autor: moep (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Prtobier mal die Lösung im Anhang. Die ist auch noch nicht perfekt,
aber vielleicht mal ein Anfang. Such mal nach "C von A bis Z" bei google

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Helfer,
expandStr3 macht alles was es soll. Wie oft wird der Speicher 
reserviert, wenn ich die Funktion 10 mal aufrufe?
/Pepe

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Aber warum bekomme ich einmal Gabi Blaubeere statt gabi?

Weil die Größe (im Sinne von nötiger Speicherplatz) von "Gabi" nicht 4, 
sondern 5 ist, und du die Null-Terminierung überschreibst. Und von 
"Blaubeere" ist die Größe sogar 10 (nicht 7). Und das "Befüllen" mittels 
strcat ist auch ziemlich gefährlich.

> Wie kann ich das lösen

Kommt darauf an, was du eigentlich ganz konkret haben willst. Du 
könntest z.B. in der Funktion ganz simpel schreiben:
innen->p_vor = "Gabi";

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Natürlich nur einmal.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein, 10 mal und jeweils am Funktionsende wieder freigegeben bzw. als 
Teil des Stacks für etwas anderes verwendet.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Ernst schrieb:
> und du die Null-Terminierung überschreibst

Ahh vielen Dank für den Hinweis. Das mit 7 und 10 kam nur wegen eines 
schnell eingefügte namens.
/pepe

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Natürlich nur einmal.

bezieht sich auf die umgeschriebene Funktion expandStr3 mit

>>  static char vorn[] = {"Gabi"};
>>  static char nachn[] = {"Blaubeere"};

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ach so, von static hatte ich hier nichts gesehen.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Komisch, wenn ich wie folgt abändere erhalte ich ein komisches Ergebnis:

void expandString2(V_N_Name *innen){
  innen->an = 7;
  innen->av = 4;
  printf("expandString2: Vorname: %s\n", innen->vor);
//    strcat(innen->vor,"Gabi");
  innen->p_vor = "Gabi";
  printf("expandString2: Vorname: %s\n", innen->vor);
//    strcat(innen->nach,"Blaubeere");
  innen->p_nach = "Blaubeere";

  printf("expandString2: Vorname: %s\n", innen->vor);
  printf("expandString2: Nachname: %s\n", innen->nach);
}

Ergebnis:
expandString2: Vorname: ‰ðg
expandString2: Vorname: ‰ðg
expandString2: Vorname: ‰ðg
expandString2: Nachname:

  innen->p_vor = "Gabi";
  innen->p_nach = "Blaubeere";

scheint nicht zu funktionieren.
Warum?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was genau erwartest du, wenn du innen->p_vor etwas zuweist, aber 
innen->vor ausgibst?

Wie gesagt, es kommt letztlich darauf an, was du überhaupt tatsächlich 
machen willst. Geht es jetzt um die Zeiger in der Struktur, oder die 
char-Arrays? Sind die Strings konstant, oder dynmisch erzeugt? usw.

Autor: Helfer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh Mann, du brauchst wirklich C Grundlagen.

Du kannst nicht nach innen->p_vor zuweisen und dann erwarten, dass du 
aus innen->vor die richtige Ausgabe bekommst. Das eine ist ein Zeiger in 
einer Struktur, das andere ein Feld in einer Struktur. Beide habe exakt 
nix miteinander zu tun, ausser dass sie Mitglied in der gleichen 
Struktur sind.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank,
ich war eben etwas unkonzentriert. Alles was ich ausprobiren wollte 
funktioniert. Vielen Dank für die Unterstützung. Thema kann geschlossen 
werden.
/Pepe

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.