Forum: Compiler & IDEs Variablen Wahn?


von tex (Gast)


Lesenswert?

Hi!
Ich kämpfe immernoch mit dem UART Problem und bin jetzt auf etwas
"unerklärliches" gestoßen.
Zur Abfrage der UART deklariere ich

char data,text[3],buffer[16]="",buffer2[16]="";

Um zu schauen, ob ich selbst der Verursacher des Datensalats bin sammle
ich die Daten
        data = UDR1;
        buffer[countit] =data;
//        data &= ~(0x80);
        buffer2[countit] =data;

Nun der Hammer!
Wenn ich die Sammlung ausgebe


  display_cursor(1,1);
  itoa(buffer[countit],text,2);
  display_string(text);
  display_cursor(1,12);
  itoa(countit,text,10);
  display_string(text);
  display_cursor(2,1);
  itoa(buffer2[countit],text,2);
  display_string(text);

Inhalt Buffer 1   Inhalt Buffer 2
0011 0001          0010 0110
0011 0000          0010 0110
0011 0001          1010 0110
0011 0000          1100 1100
0                  1000 1001
0001 0011          0001 0011
0011 0010          0011 0010

ab der Null sind die Daten dann identisch! Das ist doch nicht normal?!
Was passiert da? Läuft mir der Speicher über?

von A.K. (Gast)


Lesenswert?

Korrekt selbst festgestellt. In text[3] passen max 3 Zeichen inklusive
der abschliessenden Null. Einen 8 Bit Wert binär auszugeben braucht 9
Zeichen. Das erste itoa() überschreibt somit den Anfang vom buffer[].

von tex (Gast)


Lesenswert?

Hab ich noch nicht ganz verstanden.
Warum überschreibt text  buffer ? Ok Text ist zu klein und sollte 9
sein! aber wenn ich in text einen String reinquetsche, der in text
nicht reinpasst, warum überschreibt er dann buffer?

von Jörg Wunsch (Gast)


Lesenswert?

Er überschreibt dann irgendwas, zum Beispiel buffer.

von Sebastian (Gast)


Lesenswert?

wenn du am anfng deiner routine char data,text[3],buffer[16]
definierst,
dann wird text am irgend einer stelle im ram stehen und buffer 3
zeichen später im ram beginnen.
wenn du jetzt zb auf text[3] zugreifst, ist da das gleiche wie
buffer[0]
oder text[4]== buffer[1],
da ja dein array nur eine 16bit speicheradresse ist wo anschließend x
byte freier speicherplatz reserviert ist.

vielleicht hilft das ein wenig weiter die problematik zu verstehen

MfG
Sebastian

von Stefan May (Gast)


Lesenswert?

> char data,text[3],buffer[16]="",buffer2[16]="";

Darf ich aus der Reihenfolge schließen, wie die Variablen im RAM
abgelegt werden? Der C-Standard sagt dazu ja nix, also kann man sich
darauf nicht verlassen. Wie macht der GCC das?

ciao, Stefan.

von Chris (Gast)


Lesenswert?

> Wie macht der GCC das?

Du hast es ganz richtig erkannt, du darfst dich keinesfalls auf die
genaue Anordnung der Variablen im RAM verlassen.
Selbst wenn der gcc das in der aktuellen Version wie gewünscht macht,
sieht es in der nächsten Version vielleicht schon wieder ganz anders
aus.

von Thomas (Gast)


Lesenswert?

>Darf ich aus der Reihenfolge schließen, wie die Variablen im RAM
>abgelegt werden? Der C-Standard sagt dazu ja nix, also kann man sich
>darauf nicht verlassen. Wie macht der GCC das?

gcc wie auch viele andere compiler legen variablen in der reihenfolge
im RAM ab, wie die variablen definiert werden.

wie du selber festgestellt hast, ist das aber nicht festgelegt, und man
darf sich darauf nicht verlassen.

wenn du darauf angewiesen bist, dass variablen in einer ganz bestimmten
reihenfolge im RAM liegen, kannst du sie in eine struktur packen. aber
auch dort kann der compiler einzelne felder ausrichten, falls das für
die target CPU notwendig ist.

von tex (Gast)


Lesenswert?

OK Ok ich habs verstanden. Bleibt eine frage ...
Ich lege die Zahl sagen wir mal 21 in einer Int ab. Die ist ja von
Hause aus in ihrer Länge begrenzt. Wenn ich die jetzt per Itoa
umwandle, wieviel Zeichen brauche ich dann??
Ich ab zwar inzwischen das Machwerk von Karninghan aber Itoa steht
ziemlich weit hinten mit zig Zeichen, die mir (noch) nix sagen.
Ich versteh sowieso nicht warum C so einen Zauber aus den Variablen
macht. Bei TP war das alles viel einfacher ...

von mthomas (Gast)


Lesenswert?

http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#ga25
Moeglichen Wertebereich der uebergabenen Zahl anschauen, abhaengig von
der Basis (radix) Anzahl der moeglichen Stellen ausrechnen und noch
eins fuer die terminierende \0 dazuzaehlen. Bei Basis 10 und
moeglichen negativen Werten noch eine Stelle fuer das Vorzeichen hinzu.
Das ist alles andere als "Zauber" und etwas naeher 'an der Machine'
als in Pascal mit der versteckten Laengenangabe bei Zeichenketten. Das
K&R "Machwerk" ist stellenweise etwas anspruchsvoll, moeglicherweise
zu. Wenn das Verstaendnis gar so schwer faellt: es gibt Pascal-Compiler
fuer AVR.
(Wenn man in einem C-Forum Antworten auf solche Anfaengerfragen
erwartet, scheint es geschickt, Formulierungen wie "so einen Zauber"
oder "Machwerk" zu vermeiden. Hoffentlich die itoa-Ausfuehrungen
sorgfaeltiger gelesen als die Titelseite)

von Stefan May (Gast)


Lesenswert?

Ich trage noch eins zum Verständnis bei, weil ich Pascal hörte.

Die Strings werden im Gegensatz zu Pascal als Null-Terminierte String
gespeichert. Pascal speichert Strings AFAIK mit einem Längenbyte am
Anfang. Das gibt es in C nicht, dort wird das Ende eines String immer
mit \0 gekennzeichnet. Dazu steht im K&R eine ganze Menge.

Ich finde eigentlich nicht, daß der K&R so schwer zu verstehen ist.

mfg, Stefan.

von tex (Gast)


Lesenswert?

@MThomas
Ich fürchte, ich werde mit pascal nicht weit kommen. Es wird schon
einen Grund haben, warum die Mehrheit C-Compiler oder ASM benutzt.
Zum "Machwerk".
Eines der ersten Beispiele in dem Buch enthält nur eine Programmzeile
und die beginnt mit fprint.
Was wissen wir von fprint?
" ... gibt Zeichenkette an Standartausgabeport aus" ?? Ach was!!
Ich habe eine UART auf Pin 2 und 3, ein LCD an PC1 und noch eine UART
an  ??? und einen CAN Bus irgendwo.
Und woher weiss fprint, welches mein Standartausgabeport ist??
Kein Hinweis! Kein Querverweis. Nix!
Kann sein dass ich da von meinen Funktionsverzeichnissen und Büchern
für  Pascal, MFX, Excel - Makro, Siemens, ... verwöhnt bin.

von Stefan May (Gast)


Lesenswert?

Und wieder ein RTFM: Die Dokumentation von der AVR Libc.

http://www.nongnu.org/avr-libc/user-manual/index.html

Da ist z.B. auch die Frage nach der Länge, die Du für itoa benötigst,
beantwortet.

Der K&R ist halt nicht auf Microcontroller spezialisiert, sondern auf
Unix-Systemen. Da gibt es Printf halt. Wie sollte denn ein Hallo-Welt
auf einem Mikrocontroller aussehen? Blinken? Dann schau mal in das
Tutorial.

Hmm, mein Pascal-Buch beginnt mit einem

WriteLn("Hallo Welt");

und wo ist der Querverweis?

ciao, Stefan.

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.