Hallo, habe gerade ein paar Testzeilen auf dem TI Launchpad laufen lassen. Ich wollte lediglich die LED blinken lassen und habe deswegen geschrieben: while (1) { P1OUT ^= BIT0; unsigned short i = 50000; do{ i-- } while (i); } Die LED blinkt zwar, aber viel zu schnell. Erst wenn ich die Variable i als volatile markiere, läuft das Programm so, wie es soll. Dieses Verhalten ist mir noch nie aufgefallen. Ist dieses wegoptimieren ein "Feature" des TI-Compilers oder habe ich in der C-Vorlesung tatsächlich etwas verpennt? Viele Grüße Daniel
Ist völlig normal und zulässig. Die Schleife hat keinerlei für den Compiler erkennbare Auswirkungen, abgesehen davon dass sie mit i==0 beendet wird, und wird folglich rausgeworfen und durch i=0 ersetzt - was dann mangels weiterer Verwendung von i ebenfalls rausfliegt. "i" volatile deklarieren, oder es gleich mit Delay-Routinen richtig machen.
A. K. schrieb: > Ist völlig normal und zulässig. Die Schleife hat keinerlei für den > Compiler erkennbare Auswirkungen, abgesehen davon dass sie mit i==0 > beendet wird, und wird folglich rausgeworfen und durch i=0 ersetzt - was > dann mangels weiterer Verwendung von i ebenfalls rausfliegt. "i" > volatile deklarieren, oder es gleich mit Delay-Routinen richtig machen. Okay thx. Ich habe zwar bei vier Quellen nachgesehen, aber da wurde das nur immer für ISR so erklärt. Gut zu wissen, dass ein Compiler heutzutage schon so kleinlich ist^^
Das ist nicht kleinlich, sondern sinnvoll, schließlich soll er das Programm optimieren, damit es möglichst schnell wird...
nocheinGast schrieb: > Das ist nicht kleinlich, sondern sinnvoll, schließlich soll er das > Programm optimieren, damit es möglichst schnell wird... I komm net auf der Brennsuppn dahergschwommen. Man beachte das "^^"
Daniel schrieb: > Ich habe zwar bei vier Quellen nachgesehen, aber da wurde das > nur immer für ISR so erklärt. Gut zu wissen, dass ein Compiler > heutzutage schon so kleinlich ist Genaugenommen nicht der Compiler, sondern der Sprachstandard. Der Compiler übersetzt die Quelle gemäß der Spachspezifikation. Nicht mehr und nicht weniger. Diese Abbildung Quelle → Programm ist nicht eindeutig und kann auf unterschiedliche Art und Weise erfolgen. IdR wird eine Abbildung bevorzugt, die resourcensparend ist. Da eine Schleide wie oben keine "Wirkung auf die Welt" halt, also auf das, was im C-Standard "abstrakte Maschine" genannt wird", kann es einfach weggelassen werden, ohne die Semantik des Programms zu ändern.
Naja, prinzipiell sagt die C-Norm schon, daß im obigen Code i mit 50000 initialisiert und dann so oft dekrementiert wird, bis es 0 ist. Daß der Compiler das hier abkürzen kann, liegt an der so genannten "as-if rule", die für Optimierungen essenziell ist. Diese besagt, daß der Compiler den Code beliebig verändern darf, solange sich das "observable behavior", also das beobachtbarte Verhalten dadurch nicht ändert. Dieses Verhalten ist definiert durch File-I/O und den Zugriff auf volatile-Variablen. Deshalb ändert sich das Verhalten auch, wenn du die Zählvariable volatile machst. Jeder einzelne Zugriff auf die Variable, der im Quellcode steht, muß dann auch tatsächlich auf der Hardware durchgeführt werden.
Was zu der paradox erscheinenden Situation führt, dass
1 | while(1) { } |
als Totschleife drin gelassen werden muss, während die in ihrer praktischen Auswirkung eigentlich gleich wirkende Schleife
1 | for (int128_t i = INT128_MAX; i != 0; --i) { } |
komplett entsorgt werden darf. Manchmal sind Compiler eben Theoretiker.
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.