Ist getestet, funktioniert 1A
Was kann ich das stilistisch noch besser machen?
Wie geht das mit Pointern?
Bei mir irgendwie nicht, in dem Punkt verstehe ich mein C-Buch nicht...
Pete K. schrieb:
> Die erste For-Schleife ist schon fehlerhaft.
Bin mir nicht sicher, ob ich verstehe was du meinst.
Das Programm funktioniert so, ist mit einer manigfaltigkeit von Zahlen
getestet!
Meinst du ich hätte das Array grösser machen sollen?!
char Ziffer[10];
for(i=0;i <= 10;i++) Ziffer[i] = 0;
Dein Array umfasst 10 Elemente. Da das erste den Index 0 hat, hat das
letzte daher welchen Index?
Die for-Schleife: Welche Werte für i generiert sie?
Auf welche Indexnummern in Ziffern wird daher zugegriffen?
Nein, es geht um die Abbruchbedingung der ersten for-Schleife. Dein
Array ist 10 Stellen groß. was passiert, wenn du nun von 0 aufwärts nach
10 zählst?
_.-=: MFG :=-._
Mich wundert, dass der Überlauf nicht zum Programmabbruch führt. Hat da
der Compiler (welcher wird benutzt?) etwas wegoptimiert?
Die for(n) Schleife wird auch nur einmal durchlaufen -> überflüssig.
Außerdem fehlen die Kommentare. Das gehört zum Programmieren auch dazu
:-)
Oktoberfestbesucher schrieb:
> Das Programm funktioniert so, ist mit einer manigfaltigkeit von Zahlen> getestet!
Wichtige Programmier-Lektion:
"Programm verhält sich wie erwartet"
ist ganz und gar nicht das Gleiche wie
"Programm ist fehlerfrei"
> for(i=0;i < 32;i++)> {> unsigned char Carry_flag;> unsigned char n;
dafür hätte ich dich "verprügelt" würdest du sowas in meinem Projekt
abgeben.
Deklarationen gehören bei mir immer an den Begin einer Funktion oder an
den beginn eines C-Files. Auch wenns nach C&R überall elaubt ist suchst
du dich bei Fehlern tot.
Pete K. schrieb:
> Mich wundert, dass der Überlauf nicht zum Programmabbruch führt.
Hängt davon ab, wie die genaue Sitation am Stack bzw. im Speicher
aussieht.
> Die for(n) Schleife wird auch nur einmal durchlaufen -> überflüssig.
Doch die wird ausgeführt.
Er benutzt einen Unterlauf als Abbruchkriterium.
Sie wird sogar ziemlich oft ausgeführt. Genau 288 mal.
jl schrieb:
>> for(i=0;i < 32;i++)>> {>> unsigned char Carry_flag;>> unsigned char n;>>> dafür hätte ich dich "verprügelt" würdest du sowas in meinem Projekt> abgeben.
Dann werden wir nie in einem gemeinsamen Projekt arbeiten.
> den beginn eines C-Files. Auch wenns nach C&R überall elaubt ist suchst> du dich bei Fehlern tot.
Das genaue Gegenteil ist der Fall
Das spart Speicherplatz auf deinem Rechner... ;-)
> Deklarationen gehören bei mir ... an den beginn eines C-Files.
Ja, finde ich auch:
nur eine volatile globale Variable ist eine richtige Variable :-)
Und wozu braucht man eigentlich einen Stack?
Pink Shell schrieb:
> Lothar Miller schrieb:> Carry_flag=(Zahl&0x80000000)?1:0;>> Oder gleich so ?> Carry_flag=(Zahl&0x80000000);
Das macht aber etwas anderes :-)
> Diese x?y:z stören imho die Lesbarkeit.
Aber es kann den Unterschied ausmachen zwischen funktioniert und
funktioniert nicht :-)
Aber bitte, wenns dich stört:
Carry_flag = !!(Zahl&0x80000000);
Besser?
jl schrieb:
> Deklarationen gehören bei mir immer an den Begin einer Funktion oder an> den beginn eines C-Files. Auch wenns nach C&R überall elaubt ist suchst> du dich bei Fehlern tot.
Nö.
Lokale Variablen schreibt man immer an den Anfang des kleinsten Blocks,
in dem sie gültig sein müssen.
Der Compiler merkt zwar oft selber, wie lange eine Variable benötigt
wird, aber die Lesbarkeit wird deutlich besser, wenn man das auch klar
sieht und nicht erst 4 Seiten einer Funktion durchsuchen muß, ob die
Variable woanders noch auftaucht.
Die Schreibweise "for( uint8_t i = ..."
benutze ich sehr gerne, damit jeder sofort weiß, "i" wird nach der
Schleife nicht mehr benötigt.
Der Techniker sagt: Nur so genau, wie nötig.
Und der Programmierer sagt: Nur solange gültig, wie nötig.
Peter
Schon spannend, wie falsch man "programmieren" kann und es doch noch
irgendwie funktioniert...
Aber solbald man die Optimierung im Compiler einschaltet und der
Compiler "XYZ ist nicht definiert" aus dem Standard ernst nimmt, kracht
es.
Experte schrieb:
> Diese Kombination ist auch sehr lustig:
Wieso?
n läuft dabei doch von 9 bis 0 und die Schleife endet dann.
Nach Schleifenende ist n gleich 255 (falls "unsigned char" gleich
"uint8_t" ist).
Oder sehe ich das jetzt etwas falsch?
Karl heinz Buchegger schrieb:
> Sie wird sogar ziemlich oft ausgeführt. Genau 288 mal.
Das verstehe ich jedenfalls nicht.
Christian H. schrieb:
> Karl heinz Buchegger schrieb:>> Sie wird sogar ziemlich oft ausgeführt. Genau 288 mal.>> Das verstehe ich jedenfalls nicht.
Die äussere Schleife 32 mal, bei jeder Iteration läuft die innere
Schleife 9 mal. 32*9 = 288. D.h. der Schleifenrumpf der inneren Schleife
wird 288 mal durchgehechelt.
Peter Dannegger schrieb:
> Nö.>> Lokale Variablen schreibt man immer an den Anfang des kleinsten Blocks,> in dem sie gültig sein müssen.>> Der Compiler merkt zwar oft selber, wie lange eine Variable benötigt> wird, aber die Lesbarkeit wird deutlich besser, wenn man das auch klar> sieht und nicht erst 4 Seiten einer Funktion durchsuchen muß, ob die> Variable woanders noch auftaucht.>> Die Schreibweise "for( uint8_t i = ..."> benutze ich sehr gerne, damit jeder sofort weiß, "i" wird nach der> Schleife nicht mehr benötigt.
Jupp sehe ich auch so. Wenn man Variablen nur in einem lokalen Scope
braucht, dann sollten sie auch dort deklariert werden, aber dann auch am
anfang und nicht irgendwo in der mitte. Dann weis man gleich das man die
sich nicht die ganze Zeit merken muss, gleiches für die deklaration der
Zählervariable der For-Schleife. Der Compiler ist vielleicht so
intelligent und bekommt das hin, aber der Mensch ist kein Compiler...
>> for(i=0;i < 32;i++)>> {>> unsigned char Carry_flag;>> unsigned char n;>dafür hätte ich dich "verprügelt" würdest du sowas in meinem Projekt>abgeben.>Deklarationen gehören bei mir immer an den Begin einer Funktion oder an>den beginn eines C-Files. Auch wenns nach C&R überall elaubt ist suchst>du dich bei Fehlern tot.
ich könnte wetten du hast mit Fortran angefangen.
vielleicht dann dazwischen auf Basic umgestiegen :)
Man sucht sich höchstens dann tot, wenn man alle Variablen
überall sichtbar macht. Im schlimmsten Fall global. Information
hiding ist die Divise. Ich selbst verwende manchmal eine Variable
doppelt und dreifach im Körper einer Funktion um einfach die
Zwischenergebnisse ohne sinnvollen Namen festzuhalten. Dann
mache ich eher
int tmp;
if() {
tmp=...
}
...
if() {
tmp=...
}
statt
if() {
int tmp;
tmp=...
}
...
if() {
int tmp;
tmp=...
}
was man dann aber nicht unbeding machen sollte ist shadowing ala
int x;
if(bla) {
double x;
x=...
}
das verwirrt oft wiederum.
Christian H. schrieb:
> Wieso?> n läuft dabei doch von 9 bis 0 und die Schleife endet dann.> Nach Schleifenende ist n gleich 255 (falls "unsigned char" gleich> "uint8_t" ist).>> Oder sehe ich das jetzt etwas falsch?
Ja. Das Verhalten von
1
unsigned char n;
2
n = 0; n--;
ist undefiniert. Dass es mit einem bestimmten Compiler auf einer
bestimmten Architektur immer 255 ergibt ist (aus Sicht von C) reiner
Zufall.
Andreas
Andreas Ferber schrieb:
>> Oder sehe ich das jetzt etwas falsch?>> Ja. Das Verhalten von>
1
> unsigned char n;
2
> n = 0; n--;
3
>
> ist undefiniert.
Ähm. Nein.
Woher hast du diese Erkentnis?
Gerade dieser Fall ist exakt definiert. Für signed Typen ist
undefiniert, was passiert, aber für unsigned Typen ist festgelegt was
passieren muss
> Dass es mit einem bestimmten Compiler auf einer> bestimmten Architektur immer 255 ergibt ist (aus Sicht von C) reiner> Zufall.
Der Zufall heißt C-Standard. Und darin ist festgelegt, dass unsigned
Typen sich wie bei einem Rollover zu verhalten haben. Nach der
kleinesten Zahl, geht es mit der größten weiter.
Karl heinz Buchegger schrieb:
> Der Zufall heißt C-Standard. Und darin ist festgelegt, dass unsigned> Typen sich wie bei einem Rollover zu verhalten haben. Nach der> kleinesten Zahl, geht es mit der größten weiter.
Funktioniert allerdings nur so lange, wie unsigned char identisch zu
uint8_t ist. Wäre also ein typischer Anwendungsfall, gleich uint8_t
zu schreiben, damit es auf Maschinen, die sowas nicht haben, dann
einen Compilefehler gibt.
Allerdings würde ich mal behaupten, dass diese uint8_t-Überlauf-
Variante für eine Anzahl von Prozessoren eher eine Pessimierung
darstellt, und von guter Lesbarkeit (stand da nicht was von "wie
die großen Jungs"?) schweigen wir lieber. Eine solche krückige
Konstruktion gehört zumindest in ihrer Wirkungsweise kommentiert,
wobei der Kommentar auch gleich noch beinhalten sollte (am besten
mit der Zahl eingesparter Taktzyklen belegt), warum man solch
eine Konstruktion gewählt hat.
Ob Implementierung einer Division durch 10 in Form einer fortlaufenden
Subtraktion wirklich irgendeinen Gewinn bringt gegenüber einer normalen
Division, wage ich auch zu bezweifeln.
Jörg Wunsch schrieb:
> Ob Implementierung einer Division durch 10 in Form einer fortlaufenden> Subtraktion wirklich irgendeinen Gewinn bringt gegenüber einer normalen> Division, wage ich auch zu bezweifeln.
Auf CPUs ohne Division ist die Subtraktionsmethode deutlich schneller.
Da eine Dezimalwandlung aber nur für den viel langsameren Menschen nötig
ist, merkt man das nicht.
Diese Routine benutzt aber garnicht die Subtraktionsmethode, sondern die
dezimale Multiplikation mit 2.
Das sind hier schon stattliche 320 Schleifendurchläufe, da könnte die
Division mit Rest sogar schneller sein.
Peter
>>>> Carry_flag = (Zahl&0x80000000)?1:0;>>> Diese x?y:z stören imho die Lesbarkeit.
Karl heinz Buchegger schrieb:
>> Carry_flag = !!(Zahl&0x80000000);
Bitteschön, noch ein paar Varianten:
1
uint32_ta,b,c,d,e;
2
uint8_tz,y,x,w,v;
3
4
z=(a&0x80000000)?1:0;
5
6
y=(b&0x80000000)?!0:0;
7
8
x=!((c&(1UL<<31))?0:!0);
9
10
w=!!(d&0x80000000);
11
12
v=!!((e>>24)&0x80);
Der AVR-GCC-Compiler macht aus allen Beispielen insgesamt das selbe, nur
bei der letzten Variante wird das Ergebnis nochmal verundet:
1
lds r24, 0x0079
2
lds r25, 0x007A
3
lds r26, 0x007B
4
lds r27, 0x007C
5
eor r24, r24
6
sbrc r27, 7
7
inc r24
8
eor r25, r25
9
eor r26, r26
10
eor r27, r27
11
andi r24, 0x01 ; nur bei der letzten Variante
12
sts 0x006F, r24
Leider muß ich zugeben, dass die Variante mit der if-Abfrage am
effizientesten und schnellsten implementiert wird, weil nicht der ganze
long-Wert manipuliert wird :-(
Jörg Wunsch schrieb:
> Allerdings würde ich mal behaupten, dass diese uint8_t-Überlauf-> Variante für eine Anzahl von Prozessoren eher eine Pessimierung> darstellt, und von guter Lesbarkeit (stand da nicht was von "wie> die großen Jungs"?) schweigen wir lieber.
Absolut ACK
Die "großen Jungs" achten lieber auf Lesbarkeit anstatt auf den letzten
Taktzyklus :-)
> Ob Implementierung einer Division durch 10 in Form einer fortlaufenden> Subtraktion wirklich irgendeinen Gewinn bringt gegenüber einer normalen> Division, wage ich auch zu bezweifeln.
Das müsste man genauer durchleuchten.
Um ehrlich zu sein, habe ich diese Idee so noch nie irgendwo gesehen.
Wenn es tatsächlich um das Vermeiden von Divisionen geht, würde ich das
so machen, wie es im Ass Tutorial überall gemacht wird: Subtraktion von
10000, 1000, 100, 10 und mitzählen. 32 Bit Divisionen sind schon nicht
ohne, wenn man sie komplett in Software machen muss.
Die andere Seite der Medaille sieht so aus:
Wo wird denn so eine Umwandlung typischerweise gemacht?
Ich glaube ich lehne mich hier nicht zuweit aus dem Fenster, wenn ich
sage: In einem Prozentsatz von ungefähr 98% (sag niemals 100%, man kann
dich darauf festnageln), fällt diese Operation vor einer I/O Operation
an. Und damit ist sie in den wenigsten Fällen wirklich zeitkritisch.
Aber ich wollte den TO nicht frustrieren. Denn immerhin: Er hat sich
etwas überlegt, er hat es implementiert (von dem Schnitzer abgesehen)
und das finde ich gut. Weiter so!
Du wolltest das doch mal mit Pointern haben, oder nicht unda dazu noch
optimiert.
1
unsignedchari;
2
charZiffer[10];
3
for(i=0;i<=10;i++)Ziffer[i]=0;
1
unsignedchari;
2
charZiffer[10];
3
char*p=&Ziffer[0];
4
for(i=10;i!=0;i--)
5
{
6
*p++=0;
7
}
Überprüfung mit 0 ist schneller als <=10. Bei *p++ muss nicht jedesmal
die Adresse Ziffer[i] neu berechnet werden, da das konkret bedeutet:
*(&Ziffer[0] + i * sizeof(i))
je nach Prozessor kann *p++ in einem einzigen Befehl abgearbeitet
werden.
Gruß
Tom
P.S.: Hoffe ich hab da jetzt nicht daneben gehaunen
Martin schrieb:
> ich könnte wetten du hast mit Fortran angefangen.>> vielleicht dann dazwischen auf Basic umgestiegen :)
Ne Fortran nicht, aber 87 mit Basic und Assembler auf einem Z80.
Dann C für uC etwas Pascal/Delphi für die PC Seite.
Von Pascal hab ich etwas für mich mitgenommen wie ich etwas
strukturierter in C organisieren kann und C-Files als Objekte betrachte.
Zur lesbarkeit gibt es bei mir am Fileanfang die Deklarationen der
globalen Variablen, und alle variablen die nur in einer Funktion lokal
benutzt werden am Funktionsanfang. Da eine Funktion sowieso nicht über
1000Zeilen gehen soll braucht es nur einen kurzen Blick an den Anfang
der Funktion.
Gerade bei verteilter Entwicklung und extremer Fluktuation der
Entwickeler ist eine absolute simple Struktur von Nöten. Da dann
manchmal auch noch unerfahrene ins Projekt reinkommen aber eine
Anpassung erfolgen soll werden damit kleine Denkfehler vermindert.
Ebenso verfluche ich den Konstrukt a ? b : c, Selektive in einezelnen
Funktionen wenns klar ist und eindeutig ist ist es OK, aber was da
manchmal in geschachtelten Makros zusammengebastelt wird (das schlimmste
waren bei mir 7 ? Konstrukte über verschiedenste Makros ineinander
gesetzt) ist schon extrem Fehleranfällig.
Aber das ist hier keine Schönschreibdiskussion.
JL
"bei verteilter Entwicklung und extremer Fluktuation der
Entwickeler" würde ich mir eh' überlegen, ob C die richtige
Programmiersprache ist oder nicht eine mit strengeren (Interface-)Regeln
wie Modula oder Ada vielleicht besser wäre. Aber die Tools dürfen ja
immer nichts kosten (so gesehen die Crux von GCC). Dann reicht es auch
oft nicht mal für statische Analysetools, so deren Existenz im
"Management" überhaupt bekannt ist...
Verstehe ich nicht?! Das dürfte doch genau einmal durchlaufen...
Direkt nach dem ersten Aufruf wird N kleiner gleich 9.. somit dürfte die
Schleife beendet sein?!
Thomas Burkhart schrieb:
> Ähm, die Bedingung sagt "solange n<= als9 ist soll die Schleife> ausgeführt werden.!
Achso... ja... meine Güte so verdreht hab ichs noch nie gesehen o.O
>> Verstehe ich nicht?! Das dürfte doch genau einmal durchlaufen...> Direkt nach dem ersten Aufruf wird N kleiner gleich 9.. somit dürfte die> Schleife beendet sein?!
Schon vor dem ersten Durchlauf ist n kleinergleich 9, nämlich 9, also
gleich 9. Demnach ist die Logik wohl andersherum (while <-> until).
;-)
...
Die GROSSEN Jungs machen GROSSE Programme, die passen nur in GROSSE CPUs
mit ARM-32-Bit Architektur oder ähnlich leistungsfähigen Typen mit
GROSSEM Flash Speicher.
Damit erübrigt sich das Problem mit Division automatisch, weil die CPUs
das alle samt gut können.
Karl heinz Buchegger schrieb:
>> Ja. Das Verhalten von>>
1
>> unsigned char n;
2
>> n = 0; n--;
3
>>
>> ist undefiniert.> Ähm. Nein.> Woher hast du diese Erkentnis?
Yepp, my fault. Das im Hinterkopf verankerten "Vorsicht bei Overflow" zu
stark verschärft. IIRC hatte der GCC da in letzter Zeit auch ein paar
Optimizer-Bugs rund um das Overflow-Verhalten, so dass er
sicherheitsrelevante Range-Checks wegoptimiert hat.
Andreas
Du entwickelst für meinen Geschmack da eine Vorliebe für SChleifen, die
von einem Endwert runterzählen, obwohl sie das gar nicht müssten.
Was spricht gegen
1
for(unsignedchari=0;i<10;++i)
2
*P++=0;// Array initialisieren
Jeder C-Programmierer weltweit erkennt so ein Konstrukt sofort als
Schleife, die 10-mal durchlaufen wird. Bei jeglicher Array-Arbeit kommt
so etwas vor, es ist etwas woran sich alle gewöhnt haben und das sie aus
20 Meter Entfernung, direkt nach dem Aufstehen mit dem linken Fuss mit
verschlafenen Augen noch vor dem ersten Kaffee sofort wiedererkennen.
Bei
müssen die meisten (inklusive mir) wahrscheinlich erst mal eine
Gedenkminute einlegen, um sich davon zu überzeugen, dass das auch nur
eine Zählschleife ist, die 10 mal ausgeführt wird.
Karl heinz Buchegger schrieb:
> eine Vorliebe für SChleifen, die> von einem Endwert runterzählen, obwohl sie das gar nicht müssten.
Mache ich schon lange so, kommt von einer Vorliebe für 8051-Assembler.
Dort sieht das z.B. so aus
1
PUSH Loopcounter
2
MOV Loopcounter,#10 'Diese Schleife wird 10 mal durchlaufen
3
my_weird_loop:
4
5
6
7
8
DJNZ Loopcounter,my_weird_loop
9
POP Loopcounter
der Test ob die Schleife zuende ist ist hier sehr einfach.
Ich bin nicht beratungsresistent => also werde ich es in Zukunft so
machen wie du es schreibst.
Karl heinz Buchegger schrieb:
> Bei for(unsigned char i = 10;i;i--) *P++ = 0; // Array initialisieren>> müssen die meisten (inklusive mir) wahrscheinlich erst mal eine> Gedenkminute einlegen,
Dann gehöre ich nicht zu Deinen "meisten".
Ich finde nämlich diese Schreibweise deutlich besser zu lesen.
Bei Deiner Schreibweise kann man leicht reinfallen, wenn da i <= 10;
steht, läuft sie 11 mal. Oder wenn sie bei 1 startet, nur 9-mal.
Ich hab daher so schon mehrmals falsche Schleifenzahlen gehabt, bis ich
die schönere Schleife entdeckte.
Außerdem erzeugt das i-- den kürzeren Code, da der Vergleich gespart
wird.
Beim 8051 gibts dafür sogar den speziellen 3-fach Befehl DJNZ
(runterzählen, testen, springen), der auch keine Flags zerstört.
Peter
Manchmal wird die Schleifenzahl auch als Paramter übergeben, dann kann
man diesen gleich runterzählen und muß keine extra Hochzählvariable
verschwenden.
Peter
Peter Dannegger schrieb:
> Karl heinz Buchegger schrieb:>> Bei for(unsigned char i = 10;i;i--) *P++ = 0; // Array initialisieren>>>> müssen die meisten (inklusive mir) wahrscheinlich erst mal eine>> Gedenkminute einlegen,>> Dann gehöre ich nicht zu Deinen "meisten".
Mag sein.
Ich hab in all den Jahren schon viele Fremdlibraries studiert. Derartige
aufwärts for-Schleifen gibt es zu Millionen. Aber anders rum, hmm, da
brauch ich noch nicht mal alle 10 Finger um diejenigen der letzten 20
Jahre zu zählen :-)
> Ich finde nämlich diese Schreibweise deutlich besser zu lesen.> Bei Deiner Schreibweise kann man leicht reinfallen, wenn da i <= 10;> steht, läuft sie 11 mal.
Die Kriterien sind einfach
Startwert 0
Vergleich: kleiner
einfaches Inkrement
und natürlich überall dieselbe Variable.
dann ist es eine Zählschleife die genau so oft zählt, wie es in der
Abbruchbedingung steht.
> Außerdem erzeugt das i-- den kürzeren Code, da der Vergleich gespart> wird.> Beim 8051 gibts dafür sogar den speziellen 3-fach Befehl DJNZ> (runterzählen, testen, springen), der auch keine Flags zerstört.
Das überlass ich dem Compiler :-)
Im Ernst: Einige Optimizer, bei denen ich mir das angesehen habe,
implementieren derartige Schleifen auch durch runterzählen, wenn die
Schleifenvariable im Rumpf nicht benutzt wird. Genauso wie ein
ordentlicher Compiler
for( i = 0; i < 10; ++i )
Ziffer[i] = '\0'
das selbsttätig auf Pointerzugriff umstellt :-)
Karl heinz Buchegger schrieb:
> Ich hab in all den Jahren schon viele Fremdlibraries studiert. Derartige> aufwärts for-Schleifen gibt es zu Millionen. Aber anders rum, hmm, da> brauch ich noch nicht mal alle 10 Finger um diejenigen der letzten 20> Jahre zu zählen :-)
Kommt sicher daher, dass sie halt im K&R auch immer in dieser Form
geschrieben standen. Mir geht's hier so wie dir, und wenn man eine
Weile C programmiert, kommt man eigentlich nie wieder auf die Idee,
die Schleife bei 1 anfangen zu lassen oder <= als Endbegrenzer zu
benutzen...
>> Beim 8051 gibts dafür sogar den speziellen 3-fach Befehl DJNZ>> (runterzählen, testen, springen), der auch keine Flags zerstört.> Das überlass ich dem Compiler :-)
Du vergisst, dass Peter einen schlechten Compiler gewöhnt ist,
bei dem man als Programmierer noch voroptimieren musste. ;-)
> Im Ernst: Einige Optimizer, bei denen ich mir das angesehen habe,> implementieren derartige Schleifen auch durch runterzählen, wenn die> Schleifenvariable im Rumpf nicht benutzt wird.
1
#include<stdint.h>
2
3
uint16_t
4
arraysum(uint8_ti,constuint16_t*restrictary)
5
{
6
uint16_tsum=0;
7
#ifdef DOWN
8
while(i--!=0)
9
#else
10
for(uint8_tj=0;j<i;j++)
11
#endif
12
sum+=*ary++;
13
14
returnsum;
15
}
(mit -std=c99 compilieren, mal mit, mal ohne -DDOWN)
wird vom AVR-GCC zu zwar nicht identischem aber praktisch gleichem
Code compiliert, der sich nur leicht in der Anordnung der Assembler-
anweisungen unterscheidet.
Ich meine auch irgendwo mal gelesen zu haben das man mit unsigned
int/char sonstwas komisches dem Compiler keinen Gefallen tut und
statdessen einfach int für den Schleifenzähler verwenden sollte (der
Optimizer kann sich dann schon das beste raus suchen für den
Wertbereich).