Forum: Mikrocontroller und Digitale Elektronik WinAVR itoa Funktion


von Markus W. (kornbanane)


Lesenswert?

Hey, bin gerade etwas mit meinem Atmega16 ein bisschen mit der UART 
Schnittstelle am experimentieren. Ich programmiere in C mit dem WINAVR 
Compiler.

Will mir jetzt den Inhalt einer unsigned char Variable ausgeben und 
benutze zur Umwandlung der Ziffer in ASCI die Funktion itoa.
Man muss der Funktion ja ein char array reservieren, worin es die ASCI 
Zeichen speichert. So wie ich das Verstanden habe ergibt sich die 
minimale Arraygröße aus: Anzahl der Ziffern + Terminator.
Also für die Ziffer 255 -> Arraygröße 4, also char wert[3] (da von 
0-3=4)

Habe es jetzt mal so probiert:
1
char wert[1];
2
itoa(255,wert,10);
3
sende_string(wert);
4
sende_string("\n");

Die Arraygröße von wert ist ja jetzt eigendlich zu klein aber trotzdem 
geht es... Aber wieso ?? Normal dürfte er doch nur die ersten beiden 
Ziffern 2 und 5 abspeichern können aber ohne Terminator. Ok ich meine 
mich dran zu erinnern das in dem Fall einfach der Speicherplatz hinter 
wert[1] weitergeschrieben wird was gefährlich ist, da man keinen Zugriff 
drauf hat. Aber die Funktion sende_string überprüft den Terminator und 
wie soll er den finden wenn das Array "offziel" nur bis wert[1] geht ??



Dann noch eine andere kleine Frage: Wenn man zb. ein Windowsprogramm in 
C programmiert verwendet man zur Variablenübergabe an andere Funktionen 
ja gerne Pointer, damit es nicht zu einer Variablenkopie im 
Laufzeitsystem kommt und man Arbeitsspeicher spart. Wie verhält sich das 
bei einem Mikrocontroller hat man da auch vorteile ? Schließlich hat der 
ja keinen Arbeitsspeicher wird dann vieleicht der erzeugte Code kleiner 
??


Vielen Dank für eure Hilfe

Gruß Markus
von Krümelkeks (Gast)


Lesenswert?

Markus Wi*** schrieb:
> Schließlich hat der ja keinen Arbeitsspeicher

Wie, der hat keinen Arbeitsspeicher? RAM heißt der beim µC.
von Karl H. (kbuchegg)


Lesenswert?

Markus Wi*** schrieb:

 Also für die Ziffer 255 -> Arraygröße 4, also char wert[3] (da von
> 0-3=4)

Nein.
Um 3 Nutzzeichen zu speichern, brauchst du ein Array der Länge 4, weil 
ja das '\0' Zeichen noch hinten drann kommt.

Also wert[4];

> Habe es jetzt mal so probiert: [c]
> char wert[1];

Wenn du das Array 1 Zeichen lang machst, dann passt gerade mal die '\0' 
Terminierung da rein. Nicht sehr sinnvoll.

> Die Arraygröße von wert ist ja jetzt eigendlich zu klein aber trotzdem
> geht es...

Das sieht nur so aus.
Du bügelst Speicher nieder, der nicht zum Atrray gehört. Je nachdem wie, 
wann und wo dieser Speicher benutzt wird, kommt es irgendwann zu den 
tollsten Effekten.

> Aber wieso ??

Weil C keine Sprache für Leute ist, die eine Tante zum Lulu gehen 
brauchen. Du bist für alles verantwortlich! Wenn du etwas verbockst, 
gibt es kein Sicherheitsnetz. Wenn du Speicher niederbügelst, der dir 
nicht gehört, dann hindert dich keiner daran. Aber du musst damit 
rechnen, dass seltsame Dinge passieren. Wenn du Glück hast, dann liegen 
in diesem Speicher einfach nur andere Variablen, die dann magisch ihren 
Wert ändern. Wenn du sehr viel Glück hast, dann schmiert dir das Pgm 
einfach ab, weil du den Returnstack niedergebügelt hast. Wenn du 
allerdings Pech hast, dann gibt es zunächst überhaupt keine sichtbaren 
Auswirkungen und der Fehler wartet auf den Zeitpunkt an dem er maximalen 
Schaden anrichten kann.

> Aber die Funktion sende_string überprüft den Terminator und
> wie soll er den finden wenn das Array "offziel" nur bis wert[1] geht ??

sende_string liest den Speicher byteweise aus. Punkt.
Es hört dann auf, wenn es im Speicher auf ein 0-Byte stösst. Punkt.
Alles andere interessiert sende_string nicht. Insebsondere interessiert 
sende_string nich, ob und wenn ja wieviele Bytes zum Array gehören, 
dasss der Aufrufer bereitzustellen hat. Für sende_string gibt es nur 
Speicher und einen bestimmten Wert im Speicher, an dem es aufhört.
Remember - kein Sicherheitsnetz. Wenn im Speicher die nächsten 4 
Gigabyte kein 0-Byte kommt, dann schickt sende_string die 4 Gigabyte, 
bis es auf ein Byte mit dem Wert 0 stösst. Wenn keines kommt, dann hört 
sende_string nie auf.
von Karl H. (kbuchegg)


Lesenswert?

Für den Rest: Du brauchst ein C-Buch.
von Markus W. (kornbanane)


Lesenswert?

Hmm ok, da hast du wohl recht. Das heißt ich kann mir die Sache mit dem 
RAM so dynamisch vorstellen wie beim PC ? Das dort speicher angelegt 
wird für zb.: lokale Variablen in einer Funktion und wenn die Variablen 
bei beenden der Funktion ihre gültigkeit verliehren dann wird der 
Speicher wieder freigegeben ?

Also ist die Verwendung von Pointern hinsichtlich der beschriebenen 
Vorteile bei der PC Programmierung dann besser als eine Kopie der 
Variable zu übergeben ?
von Karl H. (kbuchegg)


Lesenswert?

Markus Wi*** schrieb:
> Hmm ok, da hast du wohl recht. Das heißt ich kann mir die Sache mit dem
> RAM so dynamisch vorstellen wie beim PC ? Das dort speicher angelegt
> wird für zb.: lokale Variablen in einer Funktion und wenn die Variablen
> bei beenden der Funktion ihre gültigkeit verliehren dann wird der
> Speicher wieder freigegeben ?

Aber Achtung:
Es wird nur die Reservierung aufgehoben. Der Speicher verschwindet 
deswegen ja nicht magisch. Der ist noch da und sein Inhalt ist auch noch 
vorhanden, bis er wieder für etwas anderes benutzt wird. Er ist nur 
nicht mehr reserviert, d.h. du kannst nicht damit rechnen, dass er 
seinen Inhalt auch behält.

> Also ist die Verwendung von Pointern hinsichtlich der beschriebenen
> Vorteile bei der PC Programmierung dann besser als eine Kopie der
> Variable zu übergeben ?

Die Frage ist nicht: was ist besser oder schlechter, sondern: was will 
ich erreichen.

Soll die Funktion auf die Variable des Aufrufers zugreifen können oder 
nicht. Wenn ja, dann brauchst du einen Pointer. Wenn nein, dann eben 
nicht. Arrays werden immer in Form eines Pointers auf das erste Element 
übergeben.
von Markus W. (kornbanane)


Lesenswert?

@ Karl Heinz Buchegger:

Ja die Sache mit dem über die Arraygrenze hinausschreiben habe ich mir 
ja schon so gedacht, habe auch mit C schon zu tun gehabt. Auch die 
Tatsache das man ziemlich viel kaputt machen kann ist mir klar nur habe 
ich bis jetzt noch nie einen µC in C programmiert und habe gedacht das 
sich da manche Sachen anders verhalten als beim PC aber is ja blödsinn 
ein PC is ja auch nur ein µC....

Noch eine Kleinigkeit, du hast geschrieben für drei Nutzzahlen braucht 
man ein Array der länge 4. Also char wert[3] oder bin ich betrunken ?? 
Von 0-3= 4 Speicherstellen ...

Gruß
von Karl H. (kbuchegg)


Lesenswert?

Markus Wi*** schrieb:
> @ Karl Heinz Buchegger:
>
> Ja die Sache mit dem über die Arraygrenze hinausschreiben habe ich mir
> ja schon so gedacht, habe auch mit C schon zu tun gehabt. Auch die
> Tatsache das man ziemlich viel kaputt machen kann ist mir klar nur habe
> ich bis jetzt noch nie einen µC in C programmiert und habe gedacht das
> sich da manche Sachen anders verhalten als beim PC aber is ja blödsinn
> ein PC is ja auch nur ein µC....

Jain.
Auf einem PC gibt es eine MMU (Memory Management Unit). Das 
Betriebssystem kann die Hardware so konfigurieren, dass es bei Zugriff 
auf Speicherseiten auf die du keinen Zugriff haben sollst zu einem 
Interrupt kommt und dir das Betriebssystem auf die Finger klopfen kann.
Auf einem AVR gibt es das alles nicht. Da ist Speicher und dort ist dein 
Programm, das wo immer es möchte in den Speicher schreiben kann und von 
dort lesen kann. Das das alles geordnet und korrekt abläuft, ist dein 
Bier.

> Noch eine Kleinigkeit, du hast geschrieben für drei Nutzzahlen braucht
> man ein Array der länge 4. Also char wert[3] oder bin ich betrunken ??

Bei der Arraydefinition gibst du die Länge an!

char wert[4];

ist ein Array der Länge 4.
Es existieren also die Einträge

   wert[0],  wert[1],  wert[2],   wert[3]

zähl nach. Sind genau 4 Stück, so wie angefordert.

du kannst dort die 3 Nutzzeichen '1', '2', '3' ablegen und als 
Stringabschluss noch die obligate 0

 wert[0] = '1';
 wert[1] = '2';
 wert[2] = '3';
 wert[3] = '\0';
von Markus W. (kornbanane)


Lesenswert?

Omg, ja sorry hab da was durcheinander gebracht. Vielen Dank für deine 
Hilfe :)
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.