Hallo,
ich habe eine Frage bezüglich des Speichers einer Übergabevariable. Bei
der folgenden Funktion wird diese ja im Stack des Controllers
gespeichert:
1
voiduart_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.
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.
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.
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?
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.
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?
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.
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.
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
>voiduart_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.
Eine eigene Frage?
Dieser Thread ist über 10 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.