zählt diese for Schleife 10mal?

Gast #2544225
Lesenswert?

> Diese for-Schleife sollte doch 10mal durchlaufen werden?

Nein, natürlich nicht.
Du solltest noch mal Zuweisung und Vergleich nachschlagen.

> Blockiert die for-schleife bei einem Thread auch alles,
> so wie die while schleife?

Sie ist wie die while-Schleife, aber ob's blockiert liegt
an dir.
Gast #2544238
Lesenswert?

Die for-Schleife wird solange durchlaufen, wie die Bedingung (in der 
Mitte) wahr ist.

Da du am Anfang schon wi auf 0 setzt, ist die Bedingung (auch wenn du 
sie mit == schreibst) falsch.

Darum for(wi=0; wi<10; wi++) und du kannst sehen, dass sie 10 mal 
durchlaufen wird.
Gast #2544343
Lesenswert?

> Wieso sollte das eine Endlosschleife sein?

Weil 'wi=9' in

> for(wi=0; wi=9; wi++)

immer [1] zu wahr auswertet (und des TOs Schleifenkörper ziemlich leer 
ist).

HTH

[1] ich setzt jetzt mal einen Integertyp voraus für wi. In C++ kann man 
da natürlich Sauereien anstellen..
Gast #2544740
Lesenswert?

Da es sich hier offensichtlich um eine kopfgesteuerte Schleife handelt, 
die nur für ehem. Basic-user von K&R eingerichtet wurde, könnte man auf 
die Idee kommen, dieses for() Konstrukt für sich über den Haufen zu 
werfen und im Sinne einer while-Schleife zu kodieren. Es ist ja nix 
anderes als das. Dann gäbe es auch nicht so viele Fragen hier im Forum 
über die korrekte Schreibweise dieser Parameter.
Also: (ich bin nur Pascal-Programmierer)
1
laufvar = 0;
2
while (laufvar <[=] ende {
3

4
  laufvar++;
5
}
Ich finde, dass das einfach übersichtlicher ist.
In Pascal schreibe ich:
1
laufvar := 0;
2
while (laufvar <[=] ende) then
3
  begin
4
    ...
5
    inc(Lauvar);
6
  end;
Ich habe beides(for.. und while(mit vorheriger Initalisierung der 
Laufvariablen)) in einem C-Programm versucht. Das generierte Hex-File 
war in beiden Fällen gleich groß.
#2544761
Lesenswert?

Johann L. schrieb:
> Peter Dannegger schrieb:
>> Auch kennen die Compiler diese Schreibweise und optimeren
>> das sehr gut, ...
>
> Es gibt Compiler, die anhand der "Schreibweise" optimieren?

Ich wollte diese Aussage selbst tatsächlich auch nicht glauben. Daher 
hier mal harte Fakten (gcc (Gentoo 4.5.3-r1 p1.0, pie-0.4.5) 4.5.3)

Ohne Optimierung:
1
int main(void) {
2
   0:  55                     push   %rbp
3
   1:  48 89 e5               mov    %rsp,%rbp
4

5
        int i;
6

7
        for(i = 0; i < 50; i++) {
8
   4:  c7 45 fc 00 00 00 00   movl   $0x0,-0x4(%rbp)
9
   b:  eb 04                  jmp    11 <main+0x11>
10
   d:  83 45 fc 01            addl   $0x1,-0x4(%rbp)
11
  11:  83 7d fc 31            cmpl   $0x31,-0x4(%rbp)
12
  15:  7e f6                  jle    d <main+0xd>
13
    asm("":::"memory");
14
        }
15

16
        for(i = 50; i; i--) {
17
  17:  c7 45 fc 32 00 00 00   movl   $0x32,-0x4(%rbp)
18
  1e:  eb 04                  jmp    24 <main+0x24>
19
  20:  83 6d fc 01            subl   $0x1,-0x4(%rbp)
20
  24:  83 7d fc 00            cmpl   $0x0,-0x4(%rbp)
21
  28:  75 f6                  jne    20 <main+0x20>
22
    asm("":::"memory");
23
        }
24

25
        return 0;
26
  2a:  b8 00 00 00 00         mov    $0x0,%eax
27
}
28
  2f:  c9                     leaveq 
29
  30:  c3                     retq

Hah! Zu früh gefreut. Schon mit O2 hingegen macht es wirklich einen 
Unterschied:
1
int main(void) {
2
   0:  b8 32 00 00 00         mov    $0x32,%eax
3
   5:  0f 1f 00               nopl   (%rax)
4

5
        int i;
6

7
        for(i = 0; i < 50; i++) {
8
   8:  83 e8 01               sub    $0x1,%eax
9
   b:  75 fb                  jne    8 <main+0x8>
10
   d:  b8 32 00 00 00         mov    $0x32,%eax
11
  12:  66 0f 1f 44 00 00      nopw   0x0(%rax,%rax,1)
12
    asm("":::"memory");
13
        }
14

15
        for(i = 50; i; i--) {
16
  18:  83 e8 01               sub    $0x1,%eax
17
  1b:  75 fb                  jne    18 <main+0x18>
18
    asm("":::"memory");
19
        }
20

21
        return 0;
22
}
23
  1d:  31 c0                  xor    %eax,%eax
24
  1f:  c3                     retq

Da das mov/nopw aber ja schon zur zweiten Schleife gehört, ist es doch 
wieder ohne Unterschied :-/
Gast #2544770
Lesenswert?

> dieses for() Konstrukt für sich über den Haufen zu
> werfen und im Sinne einer while-Schleife zu kodieren.

Könnte man.

Man könnte auch GOTOs einbauen, wenn man
strukturiertes Programmieren nicht versteht.
#2544857
Lesenswert?

Ob das Zählen aufwärts oder abwärts unterschiedlich optimiert werden 
kann, hängt grundsätzlich vom Code in der Schleife ab. Der Compiler kann 
zwar bei konstanten Bedingungen erkennen, wie viele Durchläufe es gibt 
und dementsprechend optimieren.

Das hilft aber nichts, wenn der Code in der Schleife den Zähler 
undurchsichtig verwendet, denn dann muss der Compiler sich 
standardkonform verhalten. Bei "i=0; i<50; i++" heißt das, das zuerst 
i=0 ausgeführt wird, dann i=1, dann i=2, ... Und das 
"asm("":::"memory");"  verhindert jede Optimierung, denn es schreibt 
vor, dass alle Werte von Variablen vorher davor in ihre Speicherstellen 
geschrieben werden und danach wieder geladen werden (da sie sich 
verändert haben könnten). Damit wird wieder eine Sequentialisierung 
erzwungen.

Wenn man das nicht erzwingt, kann der Compiler das sehr wohl umformen:
1
void g(void);
2

3
void f(void)
4
{
5
  int i;
6

7
  for (i = 0; i < 50; i++)
8
    g();
9
}

Hier die Ausgabe vom gcc für ARM mit -O2:
1
00000000 <f>:
2
   0:  e92d4010   push  {r4, lr}
3
   4:  e3a04032   mov  r4, #50  ; 0x32
4
   8:  ebfffffe   bl  0 <g>
5
   c:  e2544001   subs  r4, r4, #1
6
  10:  1afffffc   bne  8 <f+0x8>
7
  14:  e8bd4010   pop  {r4, lr}
8
  18:  e12fff1e   bx  lr

Man sieht, er zählt abwärts und nutzt das Zero Flag statt einem extra 
Vergleich.
#2544888
Lesenswert?

Oder in 3 Varianten:
1
void g(void);
2

3
void f(void)
4
{
5
  int i;
6

7
  for (i = 0; i < 50; i++)
8
    g();
9

10
  for (i = 50; i > 0; i--)
11
    g();
12

13
  for (i = 100; i < 200; i += 2)
14
    g();
15
}

Dieses Mal als gcc -S Ausgabe:
1
f:
2
  @ Function supports interworking.
3
  @ args = 0, pretend = 0, frame = 0
4
  @ frame_needed = 0, uses_anonymous_args = 0
5
  stmfd  sp!, {r4, lr}
6
  mov  r4, #50
7
.L2:
8
  bl  g
9
  subs  r4, r4, #1
10
  bne  .L2
11
  mov  r4, #50
12
.L3:
13
  bl  g
14
  subs  r4, r4, #1
15
  bne  .L3
16
  mov  r4, #50
17
.L4:
18
  bl  g
19
  subs  r4, r4, #1
20
  bne  .L4
21
  ldmfd  sp!, {r4, lr}
22
  bx  lr

Und wenn er noch die Inhalte der Schleifen vergleichen würde, könnte er 
das alles in eine Schleife packen… Aber das wird in realem Code wohl so 
selten auftreten, dass sich eine solche Optimierung nicht lohnt.
#2545191
Lesenswert?

Heinz schrieb:
> Da es sich hier offensichtlich um eine kopfgesteuerte Schleife handelt,
> die nur für ehem. Basic-user von K&R eingerichtet wurde,

Äh, nein.

Der Sinn der Sache in C war es, das 'Pattern'

  Initialisierung;
  while( Bedingung ) {
    Statement;
    Increment;
  }

so zu formulieren, dass die für die Schleifensteuerung wesentlichen 
Teile (Initialisierung, Bedingung und Increment) an EINER Stelle 
beisammen bleiben und nicht quer über den Code verstreut werden. Eben

  for( Initialisierung; Bedingung; Increment )
    Statement

Das hat also ganz handfeste softwaretechnische Gründe und mit Basic 
schon gleich gar nichts zu tun. For-Schleifen in Basic funktionieren 
ganz anders und zb in Fortran (wo das DO-Schleife heißt) wieder anders. 
Lass dich nicht vom Schlüsselwort blenden! Nur weil Dinge in 
verschiedenen Sprachen dasselbe Schlüsselwort benutzen, heißt das nicht, 
dass die Funktionalität identisch ist.

> die Idee kommen, dieses for() Konstrukt für sich über den Haufen zu
> werfen und im Sinne einer while-Schleife zu kodieren. Es ist ja nix
> anderes als das.

Richtig. Könnte man

> Dann gäbe es auch nicht so viele Fragen hier im Forum
> über die korrekte Schreibweise dieser Parameter.

Ist aber trotzdem der falsche Ansatz.
for hat schon seinen Sinn. Das man in der Lernphase mal Fehler macht ist 
nichts neues und auch nicht ungewöhnlich. Deswegen ist es aber nicht 
zielführend Dinge links liegen zu lassen. Nächstens kommst du dann mit 
"Da Funktionen so kompliziert sind kann man auch den Funktionscode 
direkt an der Aufrufstelle einsetzen. Ist ja im Prinzip auch nichts 
anderes."

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren