Forum: Compiler & IDEs switch anweisung / break; notwendig?


von Maggus (Gast)


Lesenswert?

Hallo,

sorry wegen der peinlichen Nachfrage, aber ich bin mir unsicher. Ist 
wohl schon zu spät am Abend. Bei genanntem Code möchte ich innerhalb der 
cases die Variable current_pause_type verändern. Wenn ich innerhalb von 
Case 1 den current_pause_type auf 2 setze, wird dann Case 2 noch 
ausgeführt? Bzw die eigentliche Frage: Ist das break; zwingend 
notwendig?
1
  switch(current_pause_type)
2
  {
3
    case 1:{break;};
4
    case 2:{break;};
5
    //case 3:{break;};
6
  }

von Karl H. (kbuchegg)


Lesenswert?

Ja, der break ist notwendig.
Ohne würdest du einen sog. 'fall through' machen:


switch( i ) {
  case 1:
    j = 5;

  case 2:
    k = 3;
    break;
}

hat i den Wert 1, dann wird sowohl die Zuweisung zu j
als auch die Zuweisung zu k ausgeführt. Die Programmausführung
fällt also gewissermassen vom case 1 zum case 2 durch, weil da
kein break ist, der dafür sorgen würde, dass das switch-case
insgesamt als beendet erklärt wird.

von Jan D. (keyman)


Lesenswert?

hallo.
also du kannst da verändern was du willst,
alle nachfolgenden befehle werden ausgeführt.
also ein break beendet logischweise das switch. lässt du das break aber 
weg, dann wird er immer den case2 auchnoch ausführen...

beispielcode (ungetestet!):
--------------------------schnipp--------------------------
 int i;
 printf("bitte zahl eingeben: ");
 scanf("%i", &i);
 switch(i) {
   case 1: i--;
   case 2: i++;
   case 3: i=5; break;
   default: i=7;
   }
 printf("i = %i\n", i);
--------------------------schnapp--------------------------

es wird, egal was du eingibst (1, 2 oder 3) immer 5 ausgeben, wenn du 
nicht 1,2 oder 3 eingibst kommt 7 raus.
alles klar?

hoffe das war einleuchtend :)

jan

von Stefan Salewski (Gast)


Lesenswert?

Deine Erklärung ist richtig, aber der ursprüngliche Fragesteller hat 
nicht nur nach dem break gefragt -- er will wohl ausserden noch 
irgendwie die Variable ( bei Dir i, bei ihm  current_pause_type) 
mittendrin verändern.

Unklare Frage -- da kann man eigentlich nicht sinnvoll antworten.

von Jan D. (keyman)


Lesenswert?

hi.
@stefan salewski: daraum hab ich mich implizit bezogen. hab ja mit 
meinem "i--;" die switch-variable bei der eingabe 1 auf 0 gestzt und 
somit wäre das dann das was er vielleicht auch ausdrücken wollte.
ist mir aber auch erst gekommen als ich den code da hingehauen habe und 
habs dann einfach so gelassen grins

@Karl heinz Buchegger: du warst schneller, das gebe ich zu :) darf ich 
zu meiner verteidigung sagen dass ich nebenher telefoniere (neudeutsch 
skype) ;-)

schönen abend
jan

von Stefan Salewski (Gast)


Lesenswert?

Sorry -- ich hatte mich auf Karl heinz Buchegger bezogen.

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


Lesenswert?

Oh, es ist wohl wieder mal an der Zeit, Duff's Device auszugraben. ;-)
1
send(to, from, count)
2
register short *to, *from;
3
register count;
4
{
5
  register n=(count+7)/8;
6
  switch(count%8){
7
  case 0:  do{  *to = *from++;
8
  case 7:    *to = *from++;
9
  case 6:    *to = *from++;
10
  case 5:    *to = *from++;
11
  case 4:    *to = *from++;
12
  case 3:    *to = *from++;
13
  case 2:    *to = *from++;
14
  case 1:    *to = *from++;
15
    }while(--n>0);
16
  }
17
}

Hier die Referenz dazu:

http://www.lysator.liu.se/c/duffs-device.html

von Karl H. (kbuchegg)


Lesenswert?

Du hast recht.
Ich hab ja die Hälfte der Fragestellung überlesen bzw.
die feinen Nuancen der Fragestellung nicht kapiert.

Ist aber logisch: Ein switch-case wertet die Bedingung nur
einmal aus, beim switch. Danach wird der dafür zuständige
case aufgesucht und von dort geht die Programmausführung
weiter bis entweder ein break angetroffen wird oder
das switch-case zu Ende ist.

Mehr steckt da nicht dahinter. Eine interessante Ausnutzung
dieser wenig-strukturierten Eigenschaft eines switch-case
ist "Duffs Device"

dabei geht es um Loop-Unrolling.
Aus
1
 do {                          /* count > 0 assumed */
2
   *to++ = *from++;              /* Note that the to pointer is NOT incremented */
3
 } while (--count > 0);

wird
1
 switch (count % 8)  /* count > 0 assumed */
2
 {
3
   case 0:        do {  *to++ = *from++;
4
   case 7:              *to++ = *from++;
5
   case 6:              *to++ = *from++;
6
   case 5:              *to++ = *from++;
7
   case 4:              *to++ = *from++;
8
   case 3:              *to++ = *from++;
9
   case 2:              *to++ = *from++;
10
   case 1:              *to++ = *from++;
11
                     } while ((count -= 8) > 0);
12
 }

Die Idee ist einfach: Anstatt in einer Schleife immer nur
ein Datenelement umzukopieren, sollen bei einem Schleifen-
durchlauf gleich mehrere Datenelemente umkopiert werden.
Das verringert den Prozentanteil der Schleifensteuerung
in der kompletten Kopierschleife.
Nur hat man ein Problem, wenn die Anzahl der umzukopierenden
Elemente nicht ganzzahlig durch die Anzahl der Kopieraktionen
in der Schleife teilbar ist. "Duffs Device" fungiert hier als
eine Art Schrägeinstieg in die Schleife und sorgt dafür
das beim ersten Schleifendurchlauf entsprechend weniger
Kopieraktionen gemacht werden.

von Karl H. (kbuchegg)


Lesenswert?

Diesmal war Jörg schneller :-)
Aber schon interessant, wie sich manchmal Gedankengänge
gleichen.

von Maggus (Gast)


Lesenswert?

Hallo,

vielen Dank für eure ausfürliche Hilfestellung.

Im Hinblick auf die Tatsache, dass das switch so im wörtlichen Sinne von 
"switch" gar kein switch ist, bedeutet das also, dass die switch 
anweisung wirklich nur exakt das gleiche bedeutet wie 
hintereinandergereihte ifs. Irgendwie hat die switch-anweisung so 
wesentlich weniger Sinn als ich zunächst annahm. BTW: Ich komme von 
Pascal her und da wird nur und ausschließlich der erste passende case 
abgearbeitet und keine weiteren.

Danke für eure Hilfe. Mir ist jetzt einiges Klarer bei den Fehlern die 
mein Code bis gerade noch produziert hatte.

Markus

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


Lesenswert?

Nein, sie ist eben nicht exakt ein geschachteltes if/else if, sondern
das wird sie nur, wenn man fein sauber das break in jedem Zweig
schreibt.  Je nach Compiler wird sie dann auch in dieser Form
implementiert (wie wohl auch bei Pascal), oder ggf. auch als
Sprungtabelle.

Die Varianten mit fehlendem break sind dagegen in Pascal so nicht
machbar.  Sie sind am ehesten vergleichbar mit etwas schrägen
Programmiertechniken, die man bei reiner Assemblerprogrammierung
machen könnte.

von Dirk (Gast)


Lesenswert?

>BTW: Ich komme von Pascal her und da wird nur und ausschließlich der erste 
>passende case abgearbeitet und keine weiteren.

Bei C wird alles bis zum ersten Break ausgefuehrt.

>Irgendwie hat die switch-anweisung so wesentlich weniger Sinn als ich >zunächst 
annahm.

Eine Switch Anweisung wird desoefteren besser vom Compiler in eine 
Sprungtabelle konvertiert als eine If - elsif Anweisung.

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.