mikrocontroller.net

Forum: Compiler & IDEs for Schleife in C


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Bernhard Kircheiss (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
[/C]
for(uint8_t lpctr = 0;lpctr != 0;lpctr++){©©©}

Wie oft wird diese Schleife ausgeführt?

0 Mal oder 256 Mal?

Wie kann ich eine Schleife mit einer uint8_t Schleifenzählervariablen 
256 Mal ausführen lassen, und das das lesbarem Code aussieht?

Autor: Walter T. (nicolas)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Bernhard Kircheiss schrieb:
> Wie oft wird diese Schleife ausgeführt?

Ersetze "©©©" durch "printf("%i", lpctr);" und finde es heraus.


Bernhard Kircheiss schrieb:
> Wie kann ich ...


do { } while;

Autor: James (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Denke das es sich hier um einen Troll handelt ist ja schon wieder 
Freitag -.-

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
uint8_t lpctr = 0;
do
{
}
while (++lptr);

: Bearbeitet durch User
Autor: Walter K. (walter_k488)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter T. schrieb:
>> Bernhard Kircheiss schrieb:
>> Wie oft wird diese Schleife ausgeführt?
>
> Ersetze "©©©" durch "printf("%i", lpctr);" und finde es heraus.
>

Was gibt es da herauszufinden?
Die Schleife wird exakt null mal durchlaufen!

Autor: leo (Gast)
Datum:

Bewertung
-5 lesenswert
nicht lesenswert
Peter D. schrieb:
> uint8_t lpctr = 0;
> do
> {
> }
> while (++lptr);

Nope. Doppelt falsch.

leo

Autor: Nicht W. (nichtsowichtig)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
leo schrieb:
> Peter D. schrieb:
>> uint8_t lpctr = 0;
>> do
>> {
>> }
>> while (++lptr);
>
> Nope. Doppelt falsch.
>
> leo

Obschon er seinen ursprünglichen Fehler bereits retuschiert hat.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
leo schrieb:
> Peter D. schrieb:
>> uint8_t lpctr = 0;
>> do
>> {
>> }
>> while (++lptr);
>
> Nope. Doppelt falsch.

Ich sehe nur einen Tippfehler (fehlendes "c" in "lptr"), den aber der TE
sicher leicht korrigieren kann.

Wo aber ist der zweite Fehler?

Autor: James (Gast)
Datum:

Bewertung
-8 lesenswert
nicht lesenswert
for(uint8_t lpctr = 0;lpctr != 0;lpctr++)
{
}

Wird Null mal durchlaufen.
for(uint8_t lpctr = 0;lpctr <= 255;lpctr++)
{
}

Wird 256 mal durchlaufen

Autor: leo (Gast)
Datum:

Bewertung
-4 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Ich sehe nur einen Tippfehler (fehlendes "c" in "lptr"), den aber der TE
> sicher leicht korrigieren kann.
>
> Wo aber ist der zweite Fehler?

Das fehlende c habe ich nicht gerechnet.
- Test auf Schleifenende fehlt am Anfang der Schleife, bzw ist an 
falscher Stelle
- durch Praeinkrement gibt es trotzdem 256 Durchlaeufe

leo

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
leo schrieb:
> - durch Praeinkrement gibt es trotzdem 256 Durchlaeufe

Genau das war allerdings das Desingziel.

Im Gegensatz zum vorgenannten Test auf 255 (sofern ihn der Compiler 
nicht gerade auf die Peda-Variante optimiert) ist der Test auf 0 nach 
dem Inkrementieren jedoch bei den meisten Maschinen "billiger" da das 
Z-Flag implizit gesetzt wird, insofern könnte Peters Variante einen Tick 
schneller sein.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
3 lesenswert
nicht lesenswert
James schrieb:
> for(uint8_t lpctr = 0;lpctr <= 255;lpctr++)
> {
> }
>
> Wird 256 mal durchlaufen

Nein, das ist eine Endlosschleife. Evtl. merkt der Compiler an, dass
lpctr<=255 immer true ist.

leo schrieb:
> - Test auf Schleifenende fehlt am Anfang der Schleife, bzw ist an
> falscher Stelle

Das ist ja gerade der Trick, um auf die gewünschten 256 Durchläufe zu
kommen.

Autor: leo (Gast)
Datum:

Bewertung
-5 lesenswert
nicht lesenswert
Jörg W. schrieb:
> insofern könnte Peters Variante einen Tick
> schneller sein.

Rechent also ev. schneller was falsches. Praktisch.

leo

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
3 lesenswert
nicht lesenswert
leo schrieb:
> Rechent also ev. schneller was falsches.

Du hast die Aufgabenstellung wohl nicht verstanden. Anders kann man dein 
Beharren auf einem angeblichen Fehler Peters (abgesehen vom Tippfehler) 
nicht deuten.

Autor: leo (Gast)
Datum:

Bewertung
-2 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Du hast die Aufgabenstellung wohl nicht verstanden.

"Wie oft wird diese Schleife ausgeführt?"

Ehem, nur die Haelfte der Fragen ;-)

leo

Autor: Alexander (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Yalu X. schrieb:
> James schrieb:
>> for(uint8_t lpctr = 0;lpctr <= 255;lpctr++)
>> {
>> }
>>
>> Wird 256 mal durchlaufen
>
> Nein, das ist eine Endlosschleife. Evtl. merkt der Compiler an, dass
> lpctr<=255 immer true ist.
>
> leo schrieb:
>> - Test auf Schleifenende fehlt am Anfang der Schleife, bzw ist an
>> falscher Stelle
>
> Das ist ja gerade der Trick, um auf die gewünschten 256 Durchläufe zu
> kommen.

Mal eine Frage wieso ist "lpctr<=255 immer true" ?

uint8_t kann doch den wert 255 erreichen

Autor: Nicht W. (nichtsowichtig)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kleinergleich?

Beitrag #5941639 wurde von einem Moderator gelöscht.
Autor: restfet (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Alexander schrieb:
> Mal eine Frage wieso ist "lpctr<=255 immer true" ?
>
> uint8_t kann doch den wert 255 erreichen

... aber den Wert 256 nicht mehr. Der "nächstgrößere" Wert nach 255 ist 
0, was die Schleifenbedingung erfüllt. Da fängt wieder alles von vorne 
an.

Beitrag #5941646 wurde von einem Moderator gelöscht.
Autor: Nicht W. (nichtsowichtig)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Jörg W. schrieb:
> leo schrieb:
>> - durch Praeinkrement gibt es trotzdem 256 Durchlaeufe
>
> Genau das war allerdings das Desingziel.
>
> Im Gegensatz zum vorgenannten Test auf 255 (sofern ihn der Compiler
> nicht gerade auf die Peda-Variante optimiert) ist der Test auf 0 nach
> dem Inkrementieren jedoch bei den meisten Maschinen "billiger" da das
> Z-Flag implizit gesetzt wird, insofern könnte Peters Variante einen Tick
> schneller sein.

Gut.

Autor: Erfolgreicher (Gast)
Datum:

Bewertung
-4 lesenswert
nicht lesenswert
Wie wärs hiermit?
while(1){
}

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Erfolgreicher schrieb:
> Wie wärs hiermit?
>
>
> while(1){
> }
> 

Auf welche magische Weise sollte sich diese Schleife nach 256 
Durchläufen beenden?

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Peter D. schrieb:
> uint8_t lpctr = 0;
> do
> {
> }
> while (++lptr);

Warum gibt's eigentlich kein do … for()? Wenn's das gäbe, könnte man es 
so schreiben:
do
{
}
for (uint8_t lpctr = 0; lcptr < 255; ++lcptr);

Alexander schrieb:
> Mal eine Frage wieso ist "lpctr<=255 immer true" ?
>
> uint8_t kann doch den wert 255 erreichen

Ja. Und wenn es den Wert 255 hat, ist es doch "kleiner oder gleich" 255, 
oder nicht? Also läuft die Schleife weiter.
Die Bedingung sagt, wenn lpctr (was ist das eigentlich für ein blöder 
Name?) kleiner oder gleich 255 ist, soll die Schleife weiter laufen. Ein 
uint8_t ist aber immer kleiner oder gleich 255, denn einen größeren 
Wert kann er gar nicht annehmen. Also läuft auch die Schleife für immer.

Jörg W. schrieb:
> Auf welche magische Weise sollte sich diese Schleife nach 256
> Durchläufen beenden?

Man drückt im richtigen Moment den RESET-Knopf? ;-)

Autor: GEKU (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernhard Kircheiss schrieb:
> lpctr != 0

Die Bedingung lpctr != 0 ist falsch, daher wird Schleife sofort 
abgebrochen und nicht ausgeführt.

http://www.c-howto.de/tutorial/schleifen/for-schleife/

Autor: Peter D. (peda)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Bernhard Kircheiss schrieb:
> und das das lesbarem Code aussieht?

Dann würde ich es so schreiben:
for (uint16_t lpctr = 256; lpctr; lpctr--)
{
}

Wenn man aus der Assemblerecke kommt, sieht das scheinbar nach ner 
riesigen Verschwendung aus. Aber oftmals ist die Routine überhaupt nicht 
zeitkritisch und dann sollte man der Lesbarkeit immer den Vorzug geben.
Ob man mit 256 vorlädt oder auf <256 vergleicht, ist reine 
Geschmackssache. Hauptsache, die 256 steht als Klartext da, wenn 256 
gemeint ist.

Autor: Heiko L. (zer0)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man kann das auch so betrachten: Um 256 Durchläufe abzuzählen sollte man 
idR einen Datentyp nehmen der 256 auch darstellen kann....

Autor: Erfolgreicher (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Auf welche magische Weise sollte sich diese Schleife nach 256
> Durchläufen beenden?

Von beenden hat der TO doch nie gesprochen ;).

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
1 lesenswert
nicht lesenswert
Heiko L. schrieb:
> Um 256 Durchläufe abzuzählen sollte man idR einen Datentyp nehmen der
> 256 auch darstellen kann....
Aus der FPGA-Ecke kommend würde ich sagen: damit verschenkt man ein 
komplettes Flipflop. Denn mit 8 Bit kann man zuverlässig 256 Zustände 
darstellen. Den vorgeschlagenen 257. Zustand braucht man dafür nicht... 
;-)

Auf einem 8-Bit µC würde ich das so angehen (inklusive der Kommentare!):
   for (unsigned char i = 0; ; ) { // Endlosschleife ...
      printf("%d  ",i);
      if (++i==0) break;           // ... nach 256 Durchläufen abbrechen
   }

Autor: Eric B. (beric)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es muss nicht immer so kompliziert sein :-P
int main() {
    uint8_t i = 0;
    do {
        printf(" %d", i);
    } while(++i != 0);
}
 https://godbolt.org/z/UF4RyI

: Bearbeitet durch User
Autor: Pong (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernhard Kircheiss schrieb:
> for(uint8_t lpctr = 0;lpctr != 0;lpctr++){©©©}


Was macht das {©©©} ?

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Pong schrieb:
> Was macht das {©©©} ?
Es ist für die Erzeugung einer Compiler-Fehlermeldung nötig.

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Lothar M. schrieb:
> Denn mit 8 Bit kann man zuverlässig 256 Zustände darstellen. Den
> vorgeschlagenen 257. Zustand braucht man dafür nicht

Streng genommen braucht man 1 Zustand für jeden Schleifendurchlauf plus
1 Zustand für den Abbruch, so dass man mit einem 8-Bit-Zähler eigentlich
nur 255 Durchläufe realisieren kann.

Wenn man aber – wie in deinem oder dem do-while-Beispiel – die Prüfung
auf Abbruch ans Ende der Schleife stellt, wird der erste Durchlauf
unabhängig vom Zustand (d.h. von der Zählvariablen) ausgeführt, so dass
er keinen eigenen Zustand benötigt. Das hat einen ähnlichen Effekt wie
wenn man bei einer Pre-Checked-Loop eine Kopie des Schleifenrumpfs vor
die eigentliche Schleife stellt. Auf diese Weise erhöht sich die
maximale Anzahl der Schleifendurchläufe um 1, so dass tatsächlich auch
256 Durchläufe möglich sind.

Autor: leo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Yalu X. schrieb:
> Streng genommen braucht man 1 Zustand für jeden Schleifendurchlauf

Ich wuerde das pragmatischer sehen: mit 8 bits kann man:
- von 0 - 255 oder
- von 1 - 256
zaehlen (usw), also max 256 Durchlaeufe.

Von 0 - 256 geht daher nicht.

leo

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:

> Dann würde ich es so schreiben:
>
> for (uint16_t lpctr = 256; lpctr; lpctr--)
> {
> }
> 
>
> Wenn man aus der Assemblerecke kommt, sieht das scheinbar nach ner
> riesigen Verschwendung aus.

Ist es auch.

> Aber oftmals ist die Routine überhaupt nicht
> zeitkritisch

Das ist ja nur ein Aspekt. Es wird auch mehr Codespace sinnlos 
verbraten.

> Hauptsache, die 256 steht als Klartext da, wenn 256
> gemeint ist.

Bitteschön:
 ldi R16,Low(256)
loop:
 ;insert loop body here
 subi R16,1
 brcc loop

6 Bytes Codespace und 256*3 Takte Schleifenoverhead. Und die 256 im 
Klartext kommt auch vor...

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
c-hater schrieb:

> Bitteschön:
>
>
>  ldi R16,Low(256)
> loop:
>  ;insert loop body here
>  subi R16,1
>  brcc loop
> 
>
> 6 Bytes Codespace und 256*3 Takte Schleifenoverhead. Und die 256 im
> Klartext kommt auch vor...

Übrigens: das ist ein Fehler versteckt! ;o)

Autor: Michael F. (michaelfu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Für den Schleifenindex würde sich uint_fast8_t anbieten, da dann der 
Compiler den effizientesten / schnellsten Datentyp für die jeweilige 
Architektur nutzen kann.

Und ein <= in der for-Schleife kann Compiler-Optimierungen (Stichwort: 
Loop-Unrolling) beeinträchtigen, da der Compiler dann vom worst-case 
einer Endlosschleife ausgehen muss...

Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
for(uint8_t lpctr=1; ©,©,©, lpctr; lpctr++;-)

Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael F. schrieb:
> Für den Schleifenindex würde sich uint_fast8_t anbieten,

Und der läuft vorhersagbar und effizient bei 255 über?

Autor: Lothar M. (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
c-hater schrieb:
>> Wenn man aus der Assemblerecke kommt, sieht das scheinbar nach ner
>> riesigen Verschwendung aus.
> Ist es auch.
Wenn man mit 8 Bit Prozessoren rummacht.

c-hater schrieb:
> Übrigens: das ist ein Fehler versteckt! ;o)
Man sollte nicht den Überlauf bzw. Unterlauf abfragen, sondern wie schon 
erwähnt das Zero-Flag.

A. S. schrieb:
> der läuft vorhersagbar und effizient bei 255 über?
fast, wie der Name schon sagt... 😉

: Bearbeitet durch Moderator
Autor: Michael F. (michaelfu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. S. schrieb:
> Michael F. schrieb:
>> Für den Schleifenindex würde sich uint_fast8_t anbieten,
>
> Und der läuft vorhersagbar und effizient bei 255 über?

Auf 8 Bit Systemen ja.

Auf 16 oder 32 Bit Systemen läuft uint_fast8_t nicht bei 255 über, ist 
aber wenigstens effizient, während bei uint8_t der Überlauf über 
Maskierung erledigt wird, was zu Lasten der Performance geht.

Wobei die Frage ist, ob man hinsichtlich Portabilität und Effizienz in C 
mit Überläufen arbeiten sollte.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael F. schrieb:
> Auf 16 oder 32 Bit Systemen läuft uint_fast8_t nicht bei 255 über,

Dann aber wieder auf manchen 64 Bit Systemen wie amd64. ;-)

Autor: GEKU (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>

int main()
{
        printf("\r\nstart\r\n");

        for(uint8_t lpctr = 0;lpctr != 0;lpctr++)
        {
                printf("lpctr %d\r\n", lpctr);
        }

        printf("ende\r\n");
}

Im Assemblercode test.s sieht man deutlich, dass zuerst die Bedingung 
(Code nach .L2) abgefragt wird. .L3 ist der Code in der Schleife.


        .arch armv6
        .eabi_attribute 28, 1
        .eabi_attribute 20, 1
        .eabi_attribute 21, 1
        .eabi_attribute 23, 3
        .eabi_attribute 24, 1
        .eabi_attribute 25, 1
        .eabi_attribute 26, 2
        .eabi_attribute 30, 6
        .eabi_attribute 34, 1
        .eabi_attribute 18, 4
        .file   "test.c"
        .text
        .section        .rodata
        .align  2
.LC0:
        .ascii  "\015\012start\015\000"
        .align  2
.LC1:
        .ascii  "lpctr %d\015\012\000"
        .align  2
.LC2:
        .ascii  "ende\015\000"
        .text
        .align  2
        .global main
        .arch armv6
        .syntax unified
        .arm
        .fpu vfp
        .type   main, %function
main:
        @ args = 0, pretend = 0, frame = 8
        @ frame_needed = 1, uses_anonymous_args = 0
        push    {fp, lr}
        add     fp, sp, #4
        sub     sp, sp, #8
        ldr     r0, .L5
        bl      puts
        mov     r3, #0
        strb    r3, [fp, #-5]
        b       .L2
.L3:
        ldrb    r3, [fp, #-5]   @ zero_extendqisi2
        mov     r1, r3
        ldr     r0, .L5+4
        bl      printf
        ldrb    r3, [fp, #-5]   @ zero_extendqisi2
        add     r3, r3, #1
        strb    r3, [fp, #-5]
.L2:
        ldrb    r3, [fp, #-5]   @ zero_extendqisi2
        cmp     r3, #0
        bne     .L3
        ldr     r0, .L5+8
        bl      puts
        mov     r3, #0
        mov     r0, r3
        sub     sp, fp, #4
        @ sp needed
        pop     {fp, pc}
.L6:
        .align  2
.L5:
        .word   .LC0
        .word   .LC1
        .word   .LC2
        .size   main, .-main
        .ident  "GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0"
        .section        .note.GNU-stack,"",%progbits


r3 enthält die Laufvariable lpctr

In Anhang run.png sieht man, dass der Code (.L3 bis .L2) innerhalb der 
Schleife nicht ausgeführt wird.

Die Laufvariable wird nach dem Schleifencode (drei Zeilen vor .L2 bis 
.L2)
inkrementiert.

Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael F. schrieb:
> Auf 16 oder 32 Bit Systemen läuft uint_fast8_t nicht bei 255 über, ist
> aber wenigstens effizient,

Ah, d.h. er macht die 4E10 Durchläufe genausi schnell, und dann ist das 
okay.

Autor: Michael F. (michaelfu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
void uint8(void)
{
  volatile uint8_t temp = 0;
  
  do
  {
    // code
  }
  while (temp++ != 255);
}

void uintfast8(void)
{
  volatile uint_fast8_t temp = 0;
  
  do
  {
    // code
  }
  while (temp++ != 255);
}

Die Schleifen in beiden Funktionen laufen von 0 - 255, was der Bedingung 
im Ausgangspost entspricht.

Hier ein Auszug aus dem List-File der IAR Embedded Workbench für Arm 
8.40.1 bezüglich Flash-Nutzung der beiden Funktionen (Cortex-M3, no 
optimization):
   Bytes  Function/Label
   -----  --------------
      28  uint8
      20  uintfast8

Somit spart die Nutzung von uint_fast8_t in diesem Beispiel 8 Bytes ein 
und der generierte Code sollte auch schneller sein...

Autor: Peter D. (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Michael F. schrieb:
> (Cortex-M3, no
> optimization):

Wenn der Compiler mit angezogener Handbremse und ausgeworfenem Anker 
läuft, interessieren die Zahlen niemanden. Nimm "-Os".

Beitrag #5945352 wurde von einem Moderator gelöscht.
Beitrag #5945407 wurde von einem Moderator gelöscht.
Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Wenn der Compiler mit angezogener Handbremse und ausgeworfenem Anker
> läuft, interessieren die Zahlen niemanden. Nimm "-Os".

Zumal der Code ja extra weired ist für uint8 mit 256 Durchläufen, wo

Peter D. schrieb:
   while(++temp); /* anpassung des namens von mir */
statt
Michael F. schrieb:
   while (temp++ != 255);
genügt hätte.

: Bearbeitet durch User
Autor: Michael F. (michaelfu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Nimm "-Os".

"-Os" bei IAR?

"high optimization for size (-Ohz)" liefert:
   Bytes  Function/Label
   -----  --------------
      26  uint8
      20  uintfast8

Und "no optimization" interessiert Leute, die im Bereich Functional 
Safety unterwegs sind und deswegen keine Optimierung nutzen sollen / 
dürfen, bzw. Leute, die sich Gedanken über die prinzipiellen 
Auswirkungen ihres C-Codes auf den generierten Code machen, bevor der 
Compiler da irgendwas dran herum optimiert...


A. S. schrieb:
> Zumal der Code ja extra weired ist für uint8 mit 256 Durchläufen

Wenn ich den Unterschied zwischen uint8_t und uint_fast8_t aufzeigen 
möchte, dann bringt es (meiner Meinung nach) wenig, wenn ich 
unterschiedliche Implementierungen für die beiden Datentypen nutze, 
weshalb die beiden beschriebenen Funktionen bis auf den gewählten 
Datentyp für den Schleifenindex identisch sind.

Das
while(++temp)
 bringt keinerlei Vorteile bei der Größe des generierten Codes, ist aber 
(ebenfalls wieder meiner Meinung nach) schlechter lesbar, als ein klares
while(temp++ != 255)
 weil so explizit der Startwert 0 und Endwert 255 der Schleife angegeben 
ist.

Autor: Jemand (Gast)
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Michael F. schrieb:
> Und "no optimization" interessiert Leute, die im Bereich Functional
> Safety unterwegs sind und deswegen keine Optimierung nutzen sollen /
> dürfen

"No optimization" ist dazu da, um kaputten Code als funktionierendes 
Produkt verkaufen zu können.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Michael F. schrieb:

> Und "no optimization" interessiert Leute, die im Bereich Functional
> Safety unterwegs sind und deswegen keine Optimierung nutzen sollen /
> dürfen

Heißt das, du hast einen Compilerhersteller, der dir ohne Optimierung 
eine Garantie auf den generierten Code gibt, mit jedoch nicht mehr?

Das wäre mir neu …

Dass das unbedingte Einzwängen auf einen 8-Bit-Datentyp auf einem 
Cortex-M eine Pessimierung ist, ist ansonsten logisch, denn es kommen 
zusätzliche Maskierungen hinzu, um die gewünschten 8 Bits aus den 
"natürlichen" 32 des Registers zu extrahieren.

Autor: Michael F. (michaelfu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Heißt das, du hast einen Compilerhersteller, der dir ohne Optimierung
> eine Garantie auf den generierten Code gibt, mit jedoch nicht mehr?

Ist jetzt sehr weit off-topic:

Das steht entweder in der FS-Norm oder im TÜV Report zur Toolchain, dass 
Optimierungen nicht empfohlen werden und wenn sie doch eingeschaltet 
werden, dann muss der optimierte Code für das komplette Debugging / 
Testing genutzt werden und man muss sich über alle Auswirkungen der 
Optimierung auf sein Projekt Gedanken machen, bzw. die Auswirkungen 
abschätzen (oder so ähnlich...)

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Michael F. schrieb:
> dann muss der optimierte Code für das komplette Debugging / Testing
> genutzt werden

Das wiederum würde ich für völlig selbstverständlich halten – das 
handhaben wir auch ganz ohne TÜV-Vorschrift so. ;-)

Unklar ist mir, warum es eine Forderung gibt, sich über die Auswirkung 
der Optimierung zu vergewissern, aber keine, sich über die Auswirkung 
der Nichtoptimierung zu vergewissern: neben größerem und langsameren 
Code verhindert ja das Ausschalten der Optimierung die Ausführung von 
Compilerschritten, die bestimmte Warnungen aktivieren, sodass am Ende 
dadurch u.U. Programmierfehler kaschiert werden können, die mit 
Optimierung entweder als Warnung oder Fehlfunktion schnell erkannt 
würden.

: Bearbeitet durch Moderator
Beitrag #5945609 wurde von einem Moderator gelöscht.
Autor: Le X. (lex_91)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Unklar ist mir, warum es eine Forderung gibt, sich über die Auswirkung
> der Optimierung zu vergewissern, aber keine, sich über die Auswirkung
> der Nichtoptimierung zu vergewissern

Das muss man halt einfach so hinnehmen.
Manche Industrien haben halt etwas schräge Vorgaben, vor allem wenn es 
um sicherheitskritische Systeme geht.

Mein Liebling ist immer:
In vielen Projekten ist die Verwendung der Standard-Library verboten.
Das führt dann dazu dass sich jeder Entwickler seineigenes memcpy usw 
zusammenfrickelt.

: Bearbeitet durch User
Autor: GEKU (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Le X. schrieb:
> Das führt dann dazu dass sich jeder Entwickler seineigenes memcpy usw
> zusammenfrickelt.

Und das soll die Qualität erhöhen und die Entwicklungskosten senken?

Le X. schrieb:
> In vielen Projekten ist die Verwendung der Standard-Library verboten.

Je öfter Libarys von verschieden Entwicklern in verschieden Projekten 
verwendet werden, umso sicherer sind diese.

Alles selber zu machen ist ein altes Entwicklerleiden.

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GEKU schrieb:
> Alles selber zu machen ist ein altes Entwicklerleiden.

Schrieb er doch auch: not invented here at its best.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GEKU schrieb:
> Je öfter Libarys von verschieden Entwicklern in verschieden Projekten
> verwendet werden, umso sicherer sind diese.

Damizufolge sollte das zu allen Zeiten von allen Leuten verwendete 
strcat äusserst sicher sein. ;-)

Lies: Wenn die Spezifikation schon scheisse ist, dann ändern Milliarden 
Fliegen auch nichts mehr daran.

Autor: Le X. (lex_91)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GEKU schrieb:
> Alles selber zu machen ist ein altes Entwicklerleiden.
Das brauchst du mir nicht erzählen.

Aber solche Auswüchse findet man halt oft in sicherheitskritischen 
Projekten.
Da wurden vor > 20 Jahren mal irgendwelche Regeln festgelegt (grade in 
der stockkonservativen Automobilindustrie) und an die traut sich niemand 
mehr ran.
Das läuft dann unter "defensive programming".
Z.B.:
- Keine Standardlib, denn die ist böse und könnte Fehler enthalten
- Keine Optimierung, denn der Compiler könnte sich ja verhaun (damit 
maskiert man freilich viele Fehler die in nicht-optimierten Code nicht 
sichtbar werden)
- dieses unsägliche if (FALSE != myConditionSatisfied()) anstatt eines 
gut lesbaren (myConditionSatisfied()== TRUE)

Das muss man aber leider so hinnehmen.
Aber wir weichen ab.

Autor: Le X. (lex_91)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Damizufolge sollte das zu allen Zeiten von allen Leuten verwendete
> strcat äusserst sicher sein. ;-)

strcat() ist broken-by-design.
Trotzdem dürfte eine Standard-Implementierung immer noch besser sein als 
ein selbstgepfriemeltes wo zu den Design-Schwächen noch die 
Programmierfehler hinzukommen ;-)

Autor: A. K. (prx)
Datum:

Bewertung
3 lesenswert
nicht lesenswert
Hinderliche Regeln sind dazu da, formal eingehalten aber effektiv 
umgangen zu werden.

Autor: DPA (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> GEKU schrieb:
>> Je öfter Libarys von verschieden Entwicklern in verschieden Projekten
>> verwendet werden, umso sicherer sind diese.
>
> Damizufolge sollte das zu allen Zeiten von allen Leuten verwendete
> strcat äusserst sicher sein. ;-)

Wenn man die länge der Strings bereits kennt und geprüft hat, spricht 
nichts gegen strcat. In dem Fall könnte man aber auch gleich memcpy oder 
strcpy verwenden.

Das tolle ist dann, wenn Leute versuchen, die wegen einer linter Warnung 
durch ein "sicheres" strncpy oder strncat zu ersetzen, und dass dann 
total versauen, und ich das dann fixen muss. Beispiel: 
https://github.com/dokan-dev/dokany/pull/677

Das hinzufügen von strncat und strncpy zum Standard war ein Fehler. 
Diese verwendet man noch fiel eher falsch, als strcat und strcpy, weil 
die Leute denken es würde die c string länge korrekt begrenzen, wofür 
diese aber garnicht gemacht sind. Ein null byte setzt strcpy aber nicht 
am Schluss: https://linux.die.net/man/3/strncpy
Und strncat ist auch super, das limitiert nicht auf n, sondern auf n+1 
Zeichen (wenn man das 0 byte mitzählt): 
https://linux.die.net/man/3/strncat

In BSD gibt es strlcat und strlcpy, die tun wenigstens was man erwarten 
würde, aber die sind leider noch in keinem C Standard: 
https://www.freebsd.org/cgi/man.cgi?query=strlcpy&sektion=3

Aber all das ist immer noch weniger problematisch, als wenn jeder seine 
eigene falsche strlcat/strlcpy version schreibt.

Autor: Eric B. (beric)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
Le X. schrieb:
> - dieses unsägliche if (FALSE != myConditionSatisfied())

Oder sogar (FALSE != myConditionNotSatisfied())
und dann der relevante Code im else-Zweig ;-)

> anstatt eines gut lesbaren (myConditionSatisfied()== TRUE)

Du meinst: (myConditionSatisfied()) // *Ohne!!* "== TRUE"

: Bearbeitet durch User
Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volle Zustimmung, Eric

Eric B. schrieb:
> Oder sogar (FALSE != myConditionNotSatisfied())
> und dann der relevante Code im else-Zweig ;-)
>
>> anstatt eines gut lesbaren (myConditionSatisfied()== TRUE)

Das hat man schon vor 2000 Jahren nicht gemacht, denn das kann man 
beliebig weit treiben:

(X)
(X==TRUE)
((X==TRUE)==TRUE)
(((X==TREU)==TRUE)==TRUE)
...
Wenn die Ampel rot ist, dann ... vs.
Wenn es wahr ist, dass die Ampel rot ist, dann ... vs.
Wenn es stimmt, dass es wahr ist, dass die Ampel rot ist, dann ...


> Du meinst: (myConditionSatisfied()) // *Ohne!!* "== TRUE"

wobei == TRUE (neben der schlechten Lesbarkeit) in C eine schlimme 
Unsitte ist, da FALSE nicht immer das Gegenteil von TRUE (oder !FALSE) 
ist.

: Bearbeitet durch User
Autor: GEKU (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Damizufolge sollte das zu allen Zeiten von allen Leuten verwendete
> strcat äusserst sicher sein. ;-)

Wenn man mit einem Werkzeug nicht umgehen kann wird's gefährlich. Gilt 
nicht nur für Entwicklungswerkzeuge.
Auch mit Zeiger kann man viel anstellen. Man muss sich der Gefahren 
bewusst sein.

C ist mehr auf Geschwindigkeit als auf Sicherheit optimiert. Das gilt 
noch mehr für Assembler Programmierung.

Codereviews sollten Probleme dieser Natur aufdecken und beseitigen.

Autor: Walter T. (nicolas)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GEKU schrieb:
> Codereviews sollten Probleme dieser Natur aufdecken und beseitigen.

Verrate bitte mehr! Woher bekomme ich als Privatperson einen Codereview? 
Wo kann man das kaufen?

: Bearbeitet durch User
Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter T. schrieb:
> Woher bekomme ich als Privatperson einen Codereview?

Von anderen Privatpersonen? ;-) Lade es bei Github hoch, finde einen 
möglichst interessanten Titel, und du wirst dich vor Reviewern nicht 
retten können. :-))

Autor: Markus F. (mfro)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> Von anderen Privatpersonen? ;-) Lade es bei Github hoch, finde einen
> möglichst interessanten Titel, und du wirst dich vor Reviewern nicht
> retten können. :-))

Da braucht's kein github. Lade deinen Code (5 Zeilen reichen) hier 
hoch und er wird nach allen (guten und schlechten) Regeln der Kunst 
auseinandergenommen.

Autor: Walter T. (nicolas)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg W. schrieb:
> und du wirst dich vor Reviewern nicht
> retten können. :-))


Hat das schonmal funktioniert?

Vielleicht sind da fortgeschrittenere Programmierer anders als ich. Aber 
ich interessiere mich nur für GitHub-Projekte, die fortgeschrittener 
sind als das, was ich selbst ohne weiteres hinbekäme. Wenn ich sehe, 
dass das Projekt weit unter meinen eigenen Kenntnissen liegt, ist es 
uninteressant, und ich widme mich wieder interessanteren Themen.

Nach der Logik wären allerdings die Leser nicht unbedingt eine Hilfe für 
den Schreiber. *)


*) Ich habe auch schon bei fremden Projekten bei der Doku geholfen. Ein 
guter Entwickler ist nicht unbedingt jemand, der gern Doku schreibt. Das 
ändert aber am Kern nichts.

Markus F. schrieb:
> Lade deinen Code (5 Zeilen reichen) hier
> hoch

Scherzkeks. Das Signal-Rausch-Verhältnis hier im Forum ist so übel, da 
ist schon ein Zweizeiler eine zweiseitige Diskussion, bei der am Ende 
nur fünf oder so sinnvolle Beiträge stehen.

Für jemanden, der lieber entwickelt, als sich mit nervigen Menschen 
herumzuschlagen, ist das Forum höchstens eine Notlösung, kein guter 
Tipp.

: Bearbeitet durch User
Autor: Malte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würde von einem Compiler anno 2019 erwarten, dass er das hier für 
einen 8-Bit-Controller so optimiert, dass intern auch mit 8 Bit 
gerechnet werden:
for (uint16_t i = 0; i < 256; i++) {...}

Also, dass diese Schleife (die besser lesbar ist) letztlich den selben 
Code erzeugt wie
uint8_t i = 0;
do {...} while (++i);

Und auch, dass es egal ist, ob man im Code hoch- oder runterzählt 
(sofern die Zählervariable sonst für nix anderes gebraucht wird 
natürlich), weil automatisch das Zero-Flag benutzt wird.

Wahrscheinlich kann der gcc das ja auch. Habe es jetzt nicht getestet. 
;)

Autor: Oliver S. (oliverso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Je nachdem, wie kurz der Schleifenkörper ist, wird der gcc den sogar 
„unrollen“.

Oliver

Autor: Michael F. (michaelfu)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Malte schrieb:
> Ich würde von einem Compiler anno 2019 erwarten, dass er das hier für
> einen 8-Bit-Controller so optimiert, dass intern auch mit 8 Bit
> gerechnet werden:
> for (uint16_t i = 0; i < 256; i++) {...}

Woher soll der Compiler wissen, dass Du ihm zwar mit uint16_t explizit 
einen 16 Bit Datentyp für i vorgibst, eigentlich aber nur 8 Bit haben 
möchtest?

Und die von Dir beschriebene for-Schleife läuft bis i = 256, bevor sie 
auf Grund der false Condition abgebrochen wird und dann sind wir 
außerhalb des 8 Bit Wertebereiches.

Autor: Egon D. (egon_d)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Walter T. schrieb:

> Aber ich interessiere mich nur für GitHub-Projekte,
> die fortgeschrittener sind als das, was ich selbst
> ohne weiteres hinbekäme. Wenn ich sehe, dass das
> Projekt weit unter meinen eigenen Kenntnissen liegt,
> ist es uninteressant, [...]

Tatsächlich?

Das bedeutet also, dass Programmieren für Dich reiner
Selbstzweck ist und keinesfalls damit zu tun hat, ein
für Dich selbst nützliches Produkt herzustellen?


> Markus F. schrieb:
>> Lade deinen Code (5 Zeilen reichen) hier hoch
>
> Scherzkeks. Das Signal-Rausch-Verhältnis hier im Forum
> ist so übel,

Nicht wirklich. Zudem ist das Signal-Rausch-Verhältnis
durchaus KEINE Konstante, sondern hängt auch davon ab,
wie Du Deine Diskussion pflegst.
Es gibt eine ganze Menge Teilnehmer, die sich nur bei
bestimmten Themen überhaupt zu Wort melden -- und auch
nur dann, wenn das Thema interessant genug und die Frage
intelligent genug ist.


> da ist schon ein Zweizeiler eine zweiseitige Diskussion,
> bei der am Ende nur fünf oder so sinnvolle Beiträge
> stehen.

Gegenfrage: Warum sollte man mit jemandem, der ein
dermaßen überhöhtes Anspruchsdenken hat, überhaupt
diskutieren wollen?
Statt zu honorieren, dass Du durch eine halbe Stunde lesen
vielleicht einen Denkanstoß bekommen hast, den Du allein
nicht gefunden hättest, beklagst Du Dich, dass es NUR fünf
oder sechs sinnvolle Beiträge sind.


> Für jemanden, der lieber entwickelt, als sich mit nervigen
> Menschen herumzuschlagen, ist das Forum höchstens eine
> Notlösung, kein guter Tipp.

Wenn Du ausschließlich für Dich selbst entwickelst, ist
das ja auch kein Problem.

Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael F. schrieb:
> Malte schrieb:
>> Ich würde von einem Compiler anno 2019 erwarten, dass er das hier für
>> einen 8-Bit-Controller so optimiert, dass intern auch mit 8 Bit
>> gerechnet werden:
>> for (uint16_t i = 0; i < 256; i++) {...}
>
> Woher soll der Compiler wissen, dass Du ihm zwar mit uint16_t explizit
> einen 16 Bit Datentyp für i vorgibst, eigentlich aber nur 8 Bit haben
> möchtest?

Der Compiler könnte durchaus erkennen, dass die Variable nur dazu dient, 
genau 256 Schleifendurchläufe zu erzeugen und dass  das auch mit 8 Bit 
geht, unter dieser Voraussetzung:

Malte schrieb:
> (sofern die Zählervariable sonst für nix anderes gebraucht wird
> natürlich)

> Und die von Dir beschriebene for-Schleife läuft bis i = 256,

Sie läuft 256 mal. Der Wert, den i später zur Laufzeit hat, und ob es 
die Variable überhaupt in der Form gibt, spielt dafür eigentlich keine 
Rolle. Sofern der in der Schleife sonst nirgends verwendet wird, kann 
sich der Optimizer da beliebig austoben, solange nur sichergestellt ist, 
dass die Schleife genau 256 Durchläufe macht.

> bevor sie auf Grund der false Condition abgebrochen wird und dann sind
> wir außerhalb des 8 Bit Wertebereiches.

Das beschreibt die Quellcode-Seite, also das was nach ISO C die 
"abstrakte Maschine" macht. Das muss nicht mit dem übereinstimmen, was 
nachher auf dem Prozessor passiert.
Wie schon erwähnt wurde, kann der Compiler auch loop-unrolling 
betreiben, also den Schleifeninhalt einfach 256 mal hinternander ins 
Executable schreiben. Dann gibt's zur Laufzeit gar kein i. Oder er kann 
eine Mischform erzeugen, also z.B. 16 mal den Schleifenkörper, und das 
in einer Schleife mit 16 Durchläufen. Dann steht zur Laufzeit was 
vollkommen anderes in der Zählvariablen.

: Bearbeitet durch User
Autor: A. S. (achs)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Malte schrieb:
> dass er das hier für einen 8-Bit-Controller so optimiert, dass intern
> auch mit 8 Bit gerechnet werden:

Er würde es vielleicht dann, wenn es sinnvoll wäre. Aber wozu sollte es 
gut sein? Um ungenutzten Stack zu sparen?

Autor: Jörg W. (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Malte schrieb:
> Ich würde von einem Compiler anno 2019 erwarten

Warum sollte die Jahreszahl daran etwas ändern?

Der AVR-GCC ist von Grund auf relativ, naja, eigenwillig aufgezogen 
worden. Soweit ich Johann (Lay) mal verstanden habe, muss man ihm daher 
alle entsprechenden Optimierungen einzeln als Mikrooptimierungen 
beibringen, denn ihm ist intern nicht abstrakt klar, dass eine 
16-Bit-Zahl eigentlich eine unnötige Verschwendung für die zugrunde 
liegende Hardware ist.

Daran ändert auch das Jahr 2019 nicht,s diese Architektur hat er seit 
ca. 20 Jahren. Solange keiner einen grundlegenden Rewrite der 
Architektur macht (und da würde sich im Jahr 2019 schon die Frage nach 
dem Verhältnis von Aufwand zu Nutzen stellen), werden sich solche Dinge 
folglich nicht rein zufällig durch eine allgemein kluge Optimierung 
ergeben.

Andere von GCC bediente Architekturen als AVR wiederum haben das Problem 
sowieso nicht. Bei denen ist das Reduzieren eines "int" auf einen 
8-Bit-Typ eher teurer als billiger.

Autor: Michael F. (michaelfu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf M. schrieb:
> Der Compiler könnte durchaus erkennen, dass die Variable nur dazu dient,
> genau 256 Schleifendurchläufe zu erzeugen und dass  das auch mit 8 Bit
> geht, unter dieser Voraussetzung:

Nachdem dem Compiler über einen "fixed data type" gesagt wird, dass er 
16 Bit für i nehmen soll, macht er das auch... Oder wie viel 
Interpretationsspielraum möchtest Du dem Compiler einräumen, an den 
Eckpunkten Deines Codes was anzupassen?
#include <stdint.h>
#include "intrinsics.h"

int main( void )
{
  for (uint16_t i = 0; i < 256; i++)
  {
    __no_operation();
  }
  

  uint8_t j = 0;
  do
  {
    __no_operation();
  }
  while (j++ != 255);
  
  return 0;
}

Ergibt mit der IAR EWAVR 7.20.1 und high optimization for low size für 
einen ATmega16:
//    4 int main( void )
main:
//    5 {
//    6   for (uint16_t i = 0; i < 256; i++)
        LDI     R30, 0
        LDI     R31, 1
//    7   {
//    8     __no_operation();
??main_0:
        NOP
//    9   }
        SBIW    R31:R30, 1
        BRNE    ??main_0
//   10   
//   11 
//   12   uint8_t j = 0;
        LDI     R16, 0
//   13   do
//   14   {
//   15     __no_operation();
??main_1:
        NOP
//   16   }
//   17   while (j++ != 255);
        DEC     R16
        BRNE    ??main_1
//   18   
//   19   return 0;
        LDI     R16, 0
        LDI     R17, 0
        RET
//   20 }

Im ersten Block werden zwei Register und die Wort-Operation SBIW 
genutzt, während im zweiten Block dann nur noch ein Register für die 
benötigten 8 Bit für j im Einsatz ist.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael F. schrieb:
> Nachdem dem Compiler über einen "fixed data type" gesagt wird, dass er
> 16 Bit für i nehmen soll, macht er das auch... Oder wie viel
> Interpretationsspielraum möchtest Du dem Compiler einräumen, an den
> Eckpunkten Deines Codes was anzupassen?

Die "as if rule" zur Optimierung gibt ihn einige Freiheit. Wenn das 
resultierende Verhalten dem entspricht, was im Rahmen der Interpretation 
anhand der Sprachdefinition im Quelltext steht, dann kann er den 
implementieren wie er will. Der Typ der Schleifenvariable definiert nur, 
was dabei rauskommen soll, also den Wertebereich, sie muss aber nicht 
exakt so implementiert werden.

Er darf die Schleifenvariable verkehrt herum zählen lassen, wenn darauf 
nicht zugegriffen wird, und wenn das günstiger ist. Er darf sie auch 
ganz weglassen, wenn er die Anzahl Iterationen auch anders 
implementieren kann.

Beispielsweise darf er eine stets Nx ausgeführte Schleife auch 
vollständig ausrollen, d.h. Nx den Code des Schleifenkörpers 
hintereinander schreiben und - sofern überhaupt verwendet - den 
jeweiligen Iteratorwert als Konstante einbringen. Oder auch auch die 
ganze Schleife weglassen, wenn das nichts am formalen Ergebnis ändert 
(darauf fallen Anfänger bei delay loops gerne herein).

Es gibt Architekturen mit speziell optimierten Schleifenkonstruktionen. 
Microchips 16-Bitter mit DSP Befehlssatz haben so etwas mit den DO 
Befehlen. Ohne Zugriff auf die Schleifenvariable sind die sehr effektiv, 
und durchaus zulässig:
    do #256, l1
    instr1
    ...
l1: instrN

Folglich darf er natürlich auch beim AVR über ein 8-Bit Register zählen, 
obwohl ein 16-Bit Typ drinsteht. Wenn das Ergebnis gleich ist.

: Bearbeitet durch User
Autor: Rolf M. (rmagnus)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael F. schrieb:
> Nachdem dem Compiler über einen "fixed data type" gesagt wird, dass er
> 16 Bit für i nehmen soll, macht er das auch... Oder wie viel
> Interpretationsspielraum möchtest Du dem Compiler einräumen, an den
> Eckpunkten Deines Codes was anzupassen?

Wieviel ich im einräumen will, spielt keine Rolle, aber wieviel ISO C 
erlaubt. Solange i nicht volatile ist, darf der Compiler damit machen 
was er will. Wie gesagt: Es zählt nur, dass die Schleife genau 256 mal 
durchlaufen wird. Wie der Compiler das umsetzt, da hat er komplett freie 
Hand.
Dass der Compiler hier davon nicht Gebrauch macht, heißt nicht, dass er 
es nicht darf.

Autor: Peter D. (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der GCC kann auch den Schleifenzähler komplett wegoptimieren, z.B.:
uint8_t data[256] = { 1, 2 };

void init_array( uint8_t* dst)
{
  uint8_t* src = data;
  for (uint16_t i = 256; i; i--)
     *dst++ = *src++;
}


ergibt:
void init_array( uint8_t* dst)
{
  8c:  dc 01         movw  r26, r24
  8e:  e0 e6         ldi  r30, 0x60  ; 96
  90:  f0 e0         ldi  r31, 0x00  ; 0
  uint8_t* src = data;
  for (uint16_t i = 256; i; i--)
     *dst++ = *src++;
  92:  81 91         ld  r24, Z+
  94:  8d 93         st  X+, r24
uint8_t data[256] = { 1, 2 };

void init_array( uint8_t* dst)
{
  uint8_t* src = data;
  for (uint16_t i = 256; i; i--)
  96:  81 e0         ldi  r24, 0x01  ; 1
  98:  e0 36         cpi  r30, 0x60  ; 96
  9a:  f8 07         cpc  r31, r24
  9c:  d1 f7         brne  .-12       ; 0x92 <init_array+0x6>
     *dst++ = *src++;
}
  9e:  08 95         ret

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.