Compiler optimiert Zählschleife weg

Gast #2390315
Lesenswert?

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
#2390318
Lesenswert?

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.
Gast #2390354
Lesenswert?

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^^
Persönliche Seite #2391601
Lesenswert?

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.
Gast #2391642
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren