Nabend,
ich versuche mich gerade an einem Minimalbeispiel:
1
#include<avr/io.h>
2
intmain(void){
3
uint8_ti,n;
4
for(i=0;i<17;i++){
5
n++;
6
}
7
}
Daraus wird allerdings im .lss:
1
int main(void)
2
{
3
b4: 80 e0 ldi r24, 0x00 ; 0
4
b6: 90 e0 ldi r25, 0x00 ; 0
5
b8: 08 95 ret
6
7
000000ba <_exit>:
8
ba: f8 94 cli
9
10
000000bc <__stop_program>:
11
bc: ff cf rjmp .-2 ; 0xbc <__stop_program>
Ich nehme an, dass durch das Makefile irgendwelche Optionen aktiviert
werden, die die Schleife eliminieren.
Könnte das jemand bei sich testen oder mir ein Makefile mit
funktionierenden Optionen zukommen lassen?
Es scheint mir aber irgendwie sinnfrei zu sein, zu untersuchen, wie eine
effiziente Umsetzung einer Schleife durch den Compiler aussieht, wenn
man dabei Optimierungen ausschaltet.
Der Beispielcode ist natürlich ähnlich sinnfrei, da einerseits n einen
undefinierten Wert hat, andererseits ein 17maliges Inkrementieren von n
das gleiche ist wie n += 17. Dazu kommt dann noch, daß weder i noch n
für irgendwas verwendet werden, also optimiert der Compiler kurzerhand
einfach alles komplett weg. So gesehen gäbe es keine Möglichkeit, die
Schleife noch effizienter umzusetzen, als es der Compiler getan hat. ;-)
Noch effizienter (allerdings nicht mehr standardkonform, GCC macht es
aber trotzdem) wird es, wenn du den Rückgabetyp von main() auf void
änderst. Dann hast du eine Funktion, die nichts macht, was irgendwas
außerhalb von ihr bewirkt, und die nichts zurückgibt. Ergebnis der
Optimierung:
ret
Effizienter geht es kaum noch, man könnte nur noch inlinen und sämtliche
Aufrufe von main() rauschmeißen [was aber wohl kein Compiler machen
würde, weil ne leere Main ja nicht gerade üblich ist]... Und wenn main()
dann also nie aufgerufen wird, dann könnte man auch den Startup-Code
weglassen... somit bleibt nicht übrig...
1.) Meckert der Compiler nicht über die fehlende return-Anweisung?
2.) Bei z.B. einem return n; dürfte der Compiler die Variable nicht so
einfach wegoptimieren? Sonst zieht er sich ja den Rückgabewert unter den
Füßen weg ;o)
> 2.) Bei z.B. einem return n; dürfte der Compiler die Variable nicht so> einfach wegoptimieren? Sonst zieht er sich ja den Rückgabewert unter den> Füßen weg ;o)
Er muß in diesen Zeilen
1
b4: 80 e0 ldi r24, 0x00 ; 0
2
b6: 90 e0 ldi r25, 0x00 ; 0
einfach die 0 durch den Wert, den n nach der Schleife hätte, ersetzen.
Rolf Magnus schrieb:
> Er muß in diesen Zeilen> einfach die 0 durch den Wert, den n nach der Schleife hätte, ersetzen.
Da n einen undefinierten Anfangswert hat, ist 0 ein absolut korrekter
return-Wert. ;-)
>> Er muß in diesen Zeilen einfach die 0 durch den Wert, den n nach der>> Schleife hätte, ersetzen.>> Da n einen undefinierten Anfangswert hat, ist 0 ein absolut korrekter> return-Wert. ;-)
Allerdings. Das wollte ich eigentlich nicht weiter ausführen. Rein aus
Interesse habe ich aber mal geschaut, was der Compiler denn tatsächlich
daraus macht, und er entscheidet sich dafür, n wie mit 0 initialisiert
zu behandeln, schreibt also einen Rückgabewert von 17 in die Register.
@jozi59:
> Zumal n auch überhaupt nicht als return value verwendet wird.
Vielleicht liest du besser nochmal nach, worauf ich geantwortet hatte.