Hallo liebe Gemeinde, ich hatte eigentlich gedacht, dass ich verstehe was "volatile" macht - aber hier verstehe ich es nicht: Code: void test() { volatile int8_t rotarySteps1 = 0; while( 1 ) { _delay_ms(1000); rotarySteps1 = 1; uart_putInt(rotarySteps1, true); uart_putInt(100 + rotarySteps1, true); uart_putInt(100 + rotarySteps1, true); uart_putInt(100 + rotarySteps1, true); } } Der Output ist: 1 1 101 132 132 32 96 196 196 196 32 96 196 196 196 32 96 Versteht einer von euch warum? (ohne volatile läuft der output wie erwartet) (auf die rotarySteps1 variable wird nirgends anders zugegriffen) Falls wichtig, die Funktion uart_putInt macht folgendes: int uart_putInt(uint8_t i, bool newLine) { char stringNumber[3]; itoa(i, stringNumber, 10 ); uart_putString (stringNumber, newLine); return 0; } Falls ich die 100+ entferne - dann kommen nur "1" Werte (wie erwartet) Danke!
Bei einer lokalen Variabel ist volatile sinnlos. Damit kann man bestenfalls dem Compiler die Optimierung verbieten und in einigen Degug-Situationen was reißen. volatile ist nur für globale Variablen sinnvoll, auf welche an mehreren Stellen zugegriffen werden kann. Also Variablen für ISR-Kommunikation oder Hardwareregister.
>volatile int8_t rotarySteps1 = 0;
Wertebereich: -128 .. +127
uint8_t i
Wertebereich: 0 .. +255
Hier solltest Du zumindest für rodentliche Verhältnisse sorgen.
Tom schrieb: > uart_putInt(100 + rotarySteps1, true); > > int uart_putInt(uint8_t i, bool newLine) > { > char stringNumber[3]; > itoa(i, stringNumber, 10 ); Buffer overflow?
Tom schrieb: > char stringNumber[3]; Was passiert, wenn Du da ein char[5] draus machst? char[3] ist ja immer zu klein bei i>99.
Dirk B. schrieb: > Irgendwelche Warnungen bei maximalem Warnlevel? Nein - leider nicht :-/ Kann es sein, dass itoa im Inneren die Variable überschreibt statt kopiert?
Falk B. schrieb: > Bei einer lokalen Variabel ist volatile sinnlos. Damit kann man > bestenfalls dem Compiler die Optimierung verbieten und in einigen > Degug-Situationen was reißen. volatile ist nur für globale Variablen > sinnvoll, auf welche an mehreren Stellen zugegriffen werden kann. Also > Variablen für ISR-Kommunikation oder Hardwareregister. Hallo Danke Falk, klar - ich will die Funktion von volatile verstehen (debuggen eines größeren Codes) - daher hier einen sehr komprimierten Code, der das Problem bereits zeigt.
Tom schrieb: > Kann es sein, dass itoa im Inneren die Variable überschreibt statt > kopiert? Der Fehler liegt vor der Tastatur. Deiner Tastatur.
Tom schrieb: > Kann es sein, dass itoa im Inneren die Variable überschreibt statt > kopiert? Nein. Denn C kennt nur Call by Value. Aber es kann ub geben, wenn Strings zu klein bemessen sind.
Tom schrieb: > Kann es sein, dass itoa im Inneren die Variable überschreibt statt > kopiert? Ja, irgendwas wird überschrieben. itoa überschreibt das, was hinter deinem char stringNumber[3] steht, wenn die Zahl einen String ergibt, der länger als 2 Zeichen ist. Also ab 100 aufwärts. Das letzte Zeichen eines Arrays, das als String verwendet wird, muß immer 0x00 sein. Das ist die Terminierung. Bis 99 geht alles gut und ab 100 fängt dein Programm an zu spinnen, da jetzt in das vierte Byte des Arrays, für das gar kein Platz reserviert ist, die Terminierung reingeschrieben wird. Das wollte dir Stephan auch schon mitteilen, hast du nur nicht kapiert: Stephan schrieb: > Was passiert, wenn Du da ein char[5] draus machst? char[3] ist ja immer > zu klein bei i>99. Also char stringNumber[4] reicht auch für eine maximal dreistellige Zahl.
:
Bearbeitet durch User
Tom schrieb: > Versteht einer von euch warum? Klar, selbstverständlich verstehe ich das. Aber erstmal zu der Unsitte, die leider weit verbreitet ist:
1 | volatile int8_t rotarySteps1 = 0; |
2 | ...
|
Was erwartest du bei so einer lokalen variable auf dem Stack? Ich empfinde es als weitaus anständiger und lesbarer, wenn man das so schreibt:
1 | int8_t rotarySteps1; |
2 | |
3 | rotarySteps1 = 0; |
4 | ...
|
Und warum? Weil man eigentlich will, daß die Variable auf dem Stack am Funktionsbeginn auf Null gesetzt wird. Das schreibt man besser ausführlich, wenn auch dies ein paar Tastendrücke mehr mit sich bringt. Dafür würdest jedoch auch DU es sogleich richtig lesen. So und nun zu 'volatile': Sowas benutzt man lediglich, um sicherzustellen, daß eine globale Variable bei mehrfacher Benutzung in einer Funktion auch wirklich jedesmal neu geladen wird und nicht durch einen Rest in irgendeinem CPU-Register lokal ersetzt wird. Es könnte ja sein, daß in der Zwischenzeit diese Variable durch jemand anderes (z.B. einen Interrupt oder eine andere grad aufgerufene Funktion oder gar die schiere Hardware des Chips) verändert wird und man das ohne jedesmaliges tatsächliches Laden gar nicht mitkriegen würde. Das 'volatile' ist eine C-spezifische Krücke, die dem geschilderten Zweck dient, da C kein wirkliches Modulsystem und eigentlich auch keine Hardware-Register kennt. Gäbe es Ausdrucksmittel in C, anhand derer der Compiler feststellen könnte, ob eine Variable von anderer Seite überhaupt veränderlich sein kann, während die aktuelle Funktion am Laufen ist oder nicht, dann könnte man sich das volatile sparen. Aber so, wie das in C ist, muß man eben manuell vor derartige Variablen ein volatile davorschreiben. Und vor lokale Variablen, die auf dem Stack liegen, ist das volatile eben verkehrt. Sowas bringt den Compiler bestenfalls durcheinander: die Variable darf er nicht auf dem Stack zwischenspeichern, jedoch liegt sie ja bereits auf dem Stack. W.S.
W.S. schrieb: > Ich empfinde es als weitaus anständiger und lesbarer, wenn man das so > schreibt: Ich nicht.
Dirk B. schrieb: > W.S. schrieb: >> Ich empfinde es als weitaus anständiger und lesbarer, wenn man das so >> schreibt: > > Ich nicht. Ich auch nicht. Aber wir wissen ja, dass W.S. keine Ahnung von C hat.
Tom schrieb: > void test() > { > volatile int8_t rotarySteps1 = 0;
1 | void test() |
2 | {
|
3 | static volatile int8_t rotarySteps1 = 0; |
Ergänzung: Mw E. schrieb: > Aber wir wissen ja, dass W.S. keine Ahnung von C hat. Was man hierran merkt: W.S. schrieb: > Und vor lokale Variablen, die auf dem Stack liegen, ist das volatile > eben verkehrt. Sowas bringt den Compiler bestenfalls durcheinander: die > Variable darf er nicht auf dem Stack zwischenspeichern, jedoch liegt sie > ja bereits auf dem Stack. volatile sagt dem Compiler/Optimierer auch, dass er Zugriffe nicht vertauschen darf. Wäre manchmal etwas blöd bei einem Peripherieregister. Bei einer normalen variable ist das egal. Daher macht volatile auf einer STack Variable nunmal Sinn. Aber W.S. ist nur mal wieder zu blöd!
Dirk B. schrieb: > Ich nicht. Das ist dann dein Problem und das derjenigen, die deine Quellen lesen müssen. Und jetzt erklär mir mal, was du dir unter volatile int8_t rotarySteps1 = 0; als tatsächliche Funktionalität des vom Compiler erzeugten Codes vorstellen würdest. Wie du siehst, hat der TO genau damit seine Probleme, die er garantiert nicht hätte, wenn er die Zuweisung der 0 an die Variable separat hingeschrieben und nicht in eine Zeile zusammengezogen hätte. Dann hätte sein Programm sogar trotz des fehlbesetzten volatile funktioniert. Viel wahrscheinlicher hätte er jedoch selbst den Unsinn erkannt und es richtig gemacht. Es gibt ne Menge Leute, ie bei Vergleichen in C grundsätzlich die Konstante zuerst schreiben: nicht if (A==3) sondern if (3==A) eben um zu vermeiden, daß man per Schussel dor eine Zuweisung produziert. Sowas ist eine Sache der inneren Disziplin - an der es hier jedoch vielen Leuten mangelt. Die wollen lieber ihre Genialität kultivieren. W.S.
W.S. schrieb: > Sowas ist eine Sache der inneren Disziplin - an der es hier > jedoch vielen Leuten mangelt. Die wollen lieber ihre Genialität > kultivieren. Ja so wie du bei deiner Debugger Verteufelung versuchst "genial" dazustehen. Nur hat eine schlaue Person mit Debugger einen fiesen Bug in deinem USB Stack entdeckt. Also belehre andere Leute nicht über Disziplin wenn du nichtmal deine eigenen auferlegten Tugenden erfüllen kannst. Du machst dich dazu nur noch mehr zur Lachnummer!
W.S. schrieb: > Das ist dann dein Problem und das derjenigen, die deine Quellen lesen > müssen. Du hast vor allem die Initialisierung von der Definition getrennt. Das soll übersichtlicher sein? du musst zweimal die Variable suchen. Mir tun deine Leser leid,
W.S. schrieb: > Was erwartest du bei so einer lokalen variable auf dem Stack? > Ich empfinde es als weitaus anständiger und lesbarer, wenn man das so > schreibt:int8_t rotarySteps1; > > rotarySteps1 = 0; Unsinn. W.S. schrieb: > Sowas benutzt man lediglich, um sicherzustellen, daß eine globale > Variable bei mehrfacher Benutzung in einer Funktion auch wirklich > jedesmal neu geladen wird und nicht durch einen Rest in irgendeinem > CPU-Register lokal ersetzt wird. Der Gebrauch von volatile muss sich nicht auf globale Variablen beschränken. > Aber so, wie das in C ist, muß man eben manuell vor derartige > Variablen ein volatile davorschreiben. Das ist in deinem heißgeliebten Delphi und Free Pascal nicht anders, nur dass es dort das volatile noch nicht so lange gibt. > Und vor lokale Variablen, die auf dem Stack liegen, ist das volatile > eben verkehrt. Sowas bringt den Compiler bestenfalls durcheinander: die > Variable darf er nicht auf dem Stack zwischenspeichern, jedoch liegt sie > ja bereits auf dem Stack. Unsinn. W.S. schrieb: > Wie du siehst, hat der TO genau damit seine Probleme, die er garantiert > nicht hätte, wenn er die Zuweisung der 0 an die Variable separat > hingeschrieben und nicht in eine Zeile zusammengezogen hätte. Unsinn. > Es gibt ne Menge Leute, ie bei Vergleichen in C grundsätzlich die > Konstante zuerst schreiben: > nicht if (A==3) > sondern if (3==A) Ich hoffe, dass diese Unsitte irgendwann einmal ausgerottet wird. Der Fehler des TE hat mit all deinen Mutmaßungen nicht das Geringste zu tun und wurde übrigens schon 20 Minuten nach seine Anfrage gefunden. Du versuchst gerade, den TE mit haltlosen Argumenten zu verwirren, nur weil er die Dreistigkeit besitzt, eine andere als die von dir favorisierte Programmiersprache zu verwenden.
:
Bearbeitet durch Moderator
Yalu X. schrieb: >> Es gibt ne Menge Leute, ie bei Vergleichen in C grundsätzlich die >> Konstante zuerst schreiben: >> nicht if (A==3) >> sondern if (3==A) > > Ich hoffe, dass diese Unsitte irgendwann einmal ausgerottet wird. Neuere GCC Versionen warnen ja schon ganz gut wenn man sich dann mal vertippt. Yalu X. schrieb: > Du > versuchst gerade, den TE mit haltlosen Argumenten zu verwirren, nur weil > er die Dreistigkeit besitzt, eine andere als die von dir favorisierte > Programmiersprache zu verwenden. Das macht er doch immer, ich wundere mich wieso er nicht noch seine unnütze Lernbetty erwähnt hat. Von der Type kommt immer nichts weiter als eine penetrante Überheblichkeit. Wenn danach wenigstens ein fachlich Korrekter und hilfreicher Beitrag käme, dann könnt man darüber hinwegsehen. Aber nein es kommt der allergrößte Unsinn aller Zeiten danach und das jedesmal. Wollt ihr den geisteskranken nicht langsam mal weglöschen? Dem seine Posts sorgen jedesmal bei vielen Leuten für Unmut. Es kommt einer seiner Posts und dann 10 dahinter die das erstmal widerlegen müssen, damit ein TE nicht verwirrt wird. Dirk B. schrieb: > Das soll übersichtlicher sein? du musst zweimal die Variable suchen. > Mir tun deine Leser leid, Was er da vorschlägt is ja noch harmlos im Vergleich zu seinem Magic Numbers und goto Versuchten Code den er hier immer versucht anzubieten wie sauer Bier.
:
Bearbeitet durch User
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.