Forum: Mikrocontroller und Digitale Elektronik Speicherort Übergabeparamter


von Kevin B. (tewger)


Lesenswert?

Hallo,

ich habe eine Frage bezüglich des Speichers einer Übergabevariable. Bei 
der folgenden Funktion wird diese ja im Stack des Controllers 
gespeichert:
1
void uart_puts (char *s)
2
{
3
    while (*s)
4
    {   uart_putc(*s);
5
        s++;
6
    }
7
}

Solange der Pointer nicht 0 ist, wird die While schleife ausgeführt. Mir 
stellt sich jetzt allerdings die Frage, ob es nicht passieren könnte, 
dass hinter der Variable noch Überreste aus vorherigen Aufrufen stehen, 
die dann auch mit gesendet werden? Oder wird durch die "" automatisch 
das \0 vom Compiler angehangen?

Ich denke dafür gibt es einen logische Antwort, allerdings bin ich noch 
nicht darauf gestoßen.

Danke.

von Peter II (Gast)


Lesenswert?

Kevin B. schrieb:
> Oder wird durch die "" automatisch
> das \0 vom Compiler angehangen?

ja, so ist ein String in C definiert

von restmuell (Gast)


Lesenswert?

Kevin B. schrieb:
> Solange der Pointer nicht 0 ist, wird die While schleife ausgeführt.

Sie wird ausgeführt, solange der Zeiger s auf eine Speicherstelle zeigt, 
deren Inhalt nicht null ist.

von mh (Gast)


Lesenswert?

Auf dem Stack landet lediglich die Adresse des Strings, nicht der String 
selbst - es wird ja ein Zeiger übergeben. Daher stellt sich Deine Frage 
nach "vorherigen Aufrufen" garnicht, ausserdem sorgt der Compiler in der 
Regel dafür, dass der Stack "ordentlich" aufgeräumt wird.

Und ja, mit "" angelegte Strings terminiert der Compiler automatisch mit 
\0.

von TEW_Ger (Gast)


Lesenswert?

Alles klar. Und der Routine wird lediglich die Adresse des ersten 
Zeichens übergeben und diese wird dann solange erhöht bis der Zeiger auf 
das \0 trifft richtig?

von Sascha (Gast)


Lesenswert?

Sobald die Funktion verlassen wird, wird der ursprüngliche Stackinhalt 
wiederhergestellt.
Macht der Compiler für dich, bei Assemblerprogrammierung muss man sich 
um nen sauberen Stack selbst kümmern.

Ergo kann da aus früheren Aufrufen nichts sein.

"Hallo" ergibt "Hallo\0", da brauchst du dich nicht drum zu kümmern. 
Ergo ist bei allem was in "" steht, das letzte Zeichen 0x00 und dadurch 
funktioniert while(s) auch.

von TEW_Ger (Gast)


Lesenswert?

mh schrieb:
> Auf dem Stack landet lediglich die Adresse des Strings, nicht der
> String
> selbst - es wird ja ein Zeiger übergeben. Daher stellt sich Deine Frage
> nach "vorherigen Aufrufen" garnicht, ausserdem sorgt der Compiler in der
> Regel dafür, dass der Stack "ordentlich" aufgeräumt wird.
>
> Und ja, mit "" angelegte Strings terminiert der Compiler automatisch mit
> \0.

wenn aber die Funktion folgendermaßen aufgerufen wird:

uart_puts("Hallo")? dann Steht im Stack Hallo\o oder?

von wendelsberg (Gast)


Lesenswert?

TEW_Ger schrieb:
> wenn aber die Funktion folgendermaßen aufgerufen wird:
>
> uart_puts("Hallo")? dann Steht im Stack Hallo\o oder?

Nein.

wendelsberg

von Stefan F. (Gast)


Lesenswert?

Nein, im Stack steht ein Zeiger auf den Anfang der Zeichenfolge

'H' 'a' 'l' 'l' 'o' '\0'

Das Text steht irgendwo anders im RAM, wo die Konstanten Strings 
gesammelt sind. Das ist auf jeden Fall nicht der Bereich des Stack.

Bei Mikrocontrollern sollte man erwägen, String im Programmspeicher 
statt im RAM abzulegen. Bei AVR geht das zum Beispiel so:

puts_P(PSTR("Hallo"));

In diesem Fall ein Zeiger auf den Programmspeicher (=Flash, nicht RAM) 
übergeben, in dem der Text steht. Und weil der Zeiger in einem anderen 
Adressrau liegt, muss man die Funtkion puts_P() verwednen, statt puts().

Deine uart Library hat hoffentlich auch *_P() Methoden für diesen Zweck.

von Sascha (Gast)


Lesenswert?

Dann steht "Hallo" (/0 spare ich mir, ist ja jetzt klar dass das immer 
dranhängt) irgendwo im Speicher, und zwar im Speichersegment wo die zur 
Laufzeit festen Variablen deklariert sind (.data).

Und wenn du das jetzt ausführst, wird nur die Adresse dieser 
Speicherstelle (die Adresse vom "H" um genau zu sein) der uart_puts 
funktion übergeben.

@wendelsberg: Ohne Begründung ist dein Post nutzlos.

von wendelsberg (Gast)


Lesenswert?

Sascha schrieb:
> @wendelsberg: Ohne Begründung ist dein Post nutzlos.

Dann sieh Dir doch die Zeile mit "uart_puts" beginnend noch mal an.

wendelsberg

von Axel S. (a-za-z0-9)


Lesenswert?

Kevin B. schrieb:
> ich habe eine Frage bezüglich des Speichers einer Übergabevariable.
> Bei der folgenden Funktion wird diese ja im Stack des Controllers
> gespeichert:

Nein.

1
> void uart_puts (char *s)
2
> {
3
...
4
> }

Parameter können, müssen aber nicht auf dem Stack übergeben werden. Die 
Übergabe in Prozessorregistern ist deutlich effizienter, funktioniert 
aber (offensichtlich) nur für wenige respektive kurze Parameter. 
Deswegen wird meist ein Mix angewandt: die ersten N Parameter werden in 
Registern übergeben, wenn es weitere Parameter gibt, wird zusätzlich der 
Stack benutzt. Diese Festlegung ist ein Teil des ABI und kann je nach 
Plattform (und manchmal auch je nach Compiler) verschieden sein. Auch 
wer den Stack aufräumt und wie das im Detail geschieht, regelt das ABI.

Dein zweiter Fehler ist, daß du davon ausgehst, der String würde als 
Kopie übergeben. Dabei sagt doch schon die Signatur der Funktion, daß da 
ein Pointer auf char übergeben wird. Der String wird zum Zeitpunkt des 
Aufrufs irgendwo im Speicher stehen (das kann sowohl RAM als auch ROM 
sein, kommt auf den Aufruf an). Der Funktion wird lediglich ein Zeiger 
auf das (vulgo: die Adresse des) ersten Zeichens übergeben.

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.