Forum: Compiler & IDEs for Schleife in C


von Bernhard Kircheiss (Gast)


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?

von Walter T. (nicolas)


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;

von James (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

1
uint8_t lpctr = 0;
2
do
3
{
4
}
5
while (++lptr);

: Bearbeitet durch User
von Walter K. (walter_k488)


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!

von leo (Gast)


Lesenswert?

Peter D. schrieb:
> uint8_t lpctr = 0;
> do
> {
> }
> while (++lptr);

Nope. Doppelt falsch.

leo

von Nicht W. (nichtsowichtig)


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.

von Yalu X. (yalu) (Moderator)


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?

von James (Gast)


Lesenswert?

1
for(uint8_t lpctr = 0;lpctr != 0;lpctr++)
2
{
3
}

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

Wird 256 mal durchlaufen

von leo (Gast)


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

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Yalu X. (yalu) (Moderator)


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.

von leo (Gast)


Lesenswert?

Jörg W. schrieb:
> insofern könnte Peters Variante einen Tick
> schneller sein.

Rechent also ev. schneller was falsches. Praktisch.

leo

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von leo (Gast)


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

von Alexander (Gast)


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

von Nicht W. (nichtsowichtig)


Lesenswert?

Kleinergleich?

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


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.
von Nicht W. (nichtsowichtig)


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.

von Erfolgreicher (Gast)


Lesenswert?

Wie wärs hiermit?
1
while(1){
2
}

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Erfolgreicher schrieb:
> Wie wärs hiermit?
>
>
1
> while(1){
2
> }
3
>

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

von Rolf M. (rmagnus)


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:
1
do
2
{
3
}
4
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? ;-)

von GEKU (Gast)


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/

von Peter D. (peda)


Lesenswert?

Bernhard Kircheiss schrieb:
> und das das lesbarem Code aussieht?

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

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.

von Heiko L. (zer0)


Lesenswert?

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

von Erfolgreicher (Gast)


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 ;).

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Angehängte Dateien:

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!):
1
   for (unsigned char i = 0; ; ) { // Endlosschleife ...
2
      printf("%d  ",i);
3
      if (++i==0) break;           // ... nach 256 Durchläufen abbrechen
4
   }

von Eric B. (beric)


Lesenswert?

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

: Bearbeitet durch User
von Pong (Gast)


Lesenswert?

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


Was macht das {©©©} ?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

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

von Yalu X. (yalu) (Moderator)


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.

von leo (Gast)


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

von c-hater (Gast)


Lesenswert?

Peter D. schrieb:

> Dann würde ich es so schreiben:
>
1
> for (uint16_t lpctr = 256; lpctr; lpctr--)
2
> {
3
> }
4
>
>
> 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:
1
 ldi R16,Low(256)
2
loop:
3
 ;insert loop body here
4
 subi R16,1
5
 brcc loop

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

von c-hater (Gast)


Lesenswert?

c-hater schrieb:

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

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

von Michael F. (Gast)


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...

von A. S. (Gast)


Lesenswert?

for(uint8_t lpctr=1; ©,©,©, lpctr; lpctr++;-)

von A. S. (Gast)


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?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


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
von Michael F. (Gast)


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.

von (prx) A. K. (prx)


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. ;-)

von GEKU (Gast)


Angehängte Dateien:

Lesenswert?

1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#include <inttypes.h>
5
6
int main()
7
{
8
        printf("\r\nstart\r\n");
9
10
        for(uint8_t lpctr = 0;lpctr != 0;lpctr++)
11
        {
12
                printf("lpctr %d\r\n", lpctr);
13
        }
14
15
        printf("ende\r\n");
16
}

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


1
        .arch armv6
2
        .eabi_attribute 28, 1
3
        .eabi_attribute 20, 1
4
        .eabi_attribute 21, 1
5
        .eabi_attribute 23, 3
6
        .eabi_attribute 24, 1
7
        .eabi_attribute 25, 1
8
        .eabi_attribute 26, 2
9
        .eabi_attribute 30, 6
10
        .eabi_attribute 34, 1
11
        .eabi_attribute 18, 4
12
        .file   "test.c"
13
        .text
14
        .section        .rodata
15
        .align  2
16
.LC0:
17
        .ascii  "\015\012start\015\000"
18
        .align  2
19
.LC1:
20
        .ascii  "lpctr %d\015\012\000"
21
        .align  2
22
.LC2:
23
        .ascii  "ende\015\000"
24
        .text
25
        .align  2
26
        .global main
27
        .arch armv6
28
        .syntax unified
29
        .arm
30
        .fpu vfp
31
        .type   main, %function
32
main:
33
        @ args = 0, pretend = 0, frame = 8
34
        @ frame_needed = 1, uses_anonymous_args = 0
35
        push    {fp, lr}
36
        add     fp, sp, #4
37
        sub     sp, sp, #8
38
        ldr     r0, .L5
39
        bl      puts
40
        mov     r3, #0
41
        strb    r3, [fp, #-5]
42
        b       .L2
43
.L3:
44
        ldrb    r3, [fp, #-5]   @ zero_extendqisi2
45
        mov     r1, r3
46
        ldr     r0, .L5+4
47
        bl      printf
48
        ldrb    r3, [fp, #-5]   @ zero_extendqisi2
49
        add     r3, r3, #1
50
        strb    r3, [fp, #-5]
51
.L2:
52
        ldrb    r3, [fp, #-5]   @ zero_extendqisi2
53
        cmp     r3, #0
54
        bne     .L3
55
        ldr     r0, .L5+8
56
        bl      puts
57
        mov     r3, #0
58
        mov     r0, r3
59
        sub     sp, fp, #4
60
        @ sp needed
61
        pop     {fp, pc}
62
.L6:
63
        .align  2
64
.L5:
65
        .word   .LC0
66
        .word   .LC1
67
        .word   .LC2
68
        .size   main, .-main
69
        .ident  "GCC: (Raspbian 8.3.0-6+rpi1) 8.3.0"
70
        .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.

von A. S. (Gast)


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.

von Michael F. (Gast)


Lesenswert?

1
void uint8(void)
2
{
3
  volatile uint8_t temp = 0;
4
  
5
  do
6
  {
7
    // code
8
  }
9
  while (temp++ != 255);
10
}
11
12
void uintfast8(void)
13
{
14
  volatile uint_fast8_t temp = 0;
15
  
16
  do
17
  {
18
    // code
19
  }
20
  while (temp++ != 255);
21
}

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):
1
   Bytes  Function/Label
2
   -----  --------------
3
      28  uint8
4
      20  uintfast8

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

von Peter D. (peda)


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.
von A. S. (Gast)


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:
1
   while(++temp); /* anpassung des namens von mir */
statt
Michael F. schrieb:
1
   while (temp++ != 255);
genügt hätte.

von Michael F. (Gast)


Lesenswert?

Peter D. schrieb:
> Nimm "-Os".

"-Os" bei IAR?

"high optimization for size (-Ohz)" liefert:
1
   Bytes  Function/Label
2
   -----  --------------
3
      26  uint8
4
      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
1
while(++temp)
 bringt keinerlei Vorteile bei der Größe des generierten Codes, ist aber 
(ebenfalls wieder meiner Meinung nach) schlechter lesbar, als ein klares
1
while(temp++ != 255)
 weil so explizit der Startwert 0 und Endwert 255 der Schleife angegeben 
ist.

von Jemand (Gast)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Michael F. (Gast)


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...)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.
von Le X. (lex_91)


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
von GEKU (Gast)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

GEKU schrieb:
> Alles selber zu machen ist ein altes Entwicklerleiden.

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

von (prx) A. K. (prx)


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.

von Le X. (lex_91)


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.

von Le X. (lex_91)


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 ;-)

von (prx) A. K. (prx)


Lesenswert?

Hinderliche Regeln sind dazu da, formal eingehalten aber effektiv 
umgangen zu werden.

von DPA (Gast)


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.

von Eric B. (beric)


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
von A. S. (Gast)


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.

von GEKU (Gast)


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.

von Walter T. (nicolas)


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
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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. :-))

von Markus F. (mfro)


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.

von Walter T. (nicolas)


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
von Malte (Gast)


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:
1
for (uint16_t i = 0; i < 256; i++) {...}

Also, dass diese Schleife (die besser lesbar ist) letztlich den selben 
Code erzeugt wie
1
uint8_t i = 0;
2
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. 
;)

von Oliver S. (oliverso)


Lesenswert?

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

Oliver

von Michael F. (Gast)


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.

von Egon D. (Gast)


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.

von Rolf M. (rmagnus)


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
von A. S. (Gast)


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?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von Michael F. (Gast)


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?
1
#include <stdint.h>
2
#include "intrinsics.h"
3
4
int main( void )
5
{
6
  for (uint16_t i = 0; i < 256; i++)
7
  {
8
    __no_operation();
9
  }
10
  
11
12
  uint8_t j = 0;
13
  do
14
  {
15
    __no_operation();
16
  }
17
  while (j++ != 255);
18
  
19
  return 0;
20
}

Ergibt mit der IAR EWAVR 7.20.1 und high optimization for low size für 
einen ATmega16:
1
//    4 int main( void )
2
main:
3
//    5 {
4
//    6   for (uint16_t i = 0; i < 256; i++)
5
        LDI     R30, 0
6
        LDI     R31, 1
7
//    7   {
8
//    8     __no_operation();
9
??main_0:
10
        NOP
11
//    9   }
12
        SBIW    R31:R30, 1
13
        BRNE    ??main_0
14
//   10   
15
//   11 
16
//   12   uint8_t j = 0;
17
        LDI     R16, 0
18
//   13   do
19
//   14   {
20
//   15     __no_operation();
21
??main_1:
22
        NOP
23
//   16   }
24
//   17   while (j++ != 255);
25
        DEC     R16
26
        BRNE    ??main_1
27
//   18   
28
//   19   return 0;
29
        LDI     R16, 0
30
        LDI     R17, 0
31
        RET
32
//   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.

von (prx) A. K. (prx)


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:
1
    do #256, l1
2
    instr1
3
    ...
4
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
von Rolf M. (rmagnus)


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.

von Peter D. (peda)


Lesenswert?

Der GCC kann auch den Schleifenzähler komplett wegoptimieren, z.B.:
1
uint8_t data[256] = { 1, 2 };
2
3
void init_array( uint8_t* dst)
4
{
5
  uint8_t* src = data;
6
  for (uint16_t i = 256; i; i--)
7
     *dst++ = *src++;
8
}

ergibt:
1
void init_array( uint8_t* dst)
2
{
3
  8c:  dc 01         movw  r26, r24
4
  8e:  e0 e6         ldi  r30, 0x60  ; 96
5
  90:  f0 e0         ldi  r31, 0x00  ; 0
6
  uint8_t* src = data;
7
  for (uint16_t i = 256; i; i--)
8
     *dst++ = *src++;
9
  92:  81 91         ld  r24, Z+
10
  94:  8d 93         st  X+, r24
11
uint8_t data[256] = { 1, 2 };
12
13
void init_array( uint8_t* dst)
14
{
15
  uint8_t* src = data;
16
  for (uint16_t i = 256; i; i--)
17
  96:  81 e0         ldi  r24, 0x01  ; 1
18
  98:  e0 36         cpi  r30, 0x60  ; 96
19
  9a:  f8 07         cpc  r31, r24
20
  9c:  d1 f7         brne  .-12       ; 0x92 <init_array+0x6>
21
     *dst++ = *src++;
22
}
23
  9e:  08 95         ret

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
Noch kein Account? Hier anmelden.