[geloest] C (?): bestimmte Verschachtelung von switch und if

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

[geloest] C (?): bestimmte Verschachtelung von switch und if

Beitrag von Cae » 11.11.2012 05:59:23

Hallo zusammen,

vor einiger Zeit habe ich einen Code gelesen, wo ifs in einer bestimmten Art innerhalb eines switch-Statements verteilt waren. Nun weiss ich aber nicht mehr a) wie dieser Stil heisst, b) wie die Struktur aussieht oder c) ob es ueberhaupt C war.

Ich gehe mal von C aus und diesem Code (ja, die breaks sind ueberfluessig):

Code: Alles auswählen

int main(void) {
	switch (3) {
		if (0) {
			case 1:
				return 1;
				break;
		} else if (1) {
			case 2:
				return 2;
				break;
		} else if (0) {
			case 3:
				return 3;
				break;
		} else if (1) {
			case 4:
				return 4;
				break;
		}
			default:
				return 42;
				break;
	}

	return 0;
}
Passieren tut natuerlich nix. Die (else-) ifs werden scheinbar gar nicht ausgewertet, heraus kommt 3.

Kommt jemandem dieser Aufbau bekannt vor und mag mir sagen, wie sich das nennt? Ich erinnere mich an die Beschreibung, es sei eigentlich ein Hack, aber nach POSIX (?) oder einem anderen Standard gefordert oder nicht explizit ausgeschlossen.

Wenn man nach "C switch if else Verschachtelung" (oder dem englischen Aequivalent) sucht, bekommt man haufenweise Grundlagen zu dem Thema, von C# ueber Perl nach C++. Wenn ich in den Kernel-Sourcen nach Zeilen mit if suche, die von case-Zeilen gefolgt werden, finde ich keine Strukturen dieser Art [1].

Gruss Cae

[1] off-topic: wie kann man gescheit nur innerhalb oder ausserhalb von Kommentaren in Code greppen?
Zuletzt geändert von Cae am 12.11.2012 17:59:52, insgesamt 1-mal geändert.
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Liffi
Beiträge: 2345
Registriert: 02.10.2004 01:33:05

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Liffi » 11.11.2012 10:09:23

Cae hat geschrieben: [1] off-topic: wie kann man gescheit nur innerhalb oder ausserhalb von Kommentaren in Code greppen?
Einmal durch ein

Code: Alles auswählen

grep -vE "^(\/\/|\/\*|\*)"
Durchpipen um die Kommentare rauszufiltern. Wobei ich da im Moment noch ignoriere, dass vor den Kommentaren noch Whitespace sein darf.

Um den Stil zu finden würde ich mal "nested switch case if else" versuchen (falls das nicht dein englisches Äquivalent war). Bin mir aber nicht sicher, ob es den gibt. In der 'freien Natur' bin ich noch nie auf etwas derartiges gestoßen.

EDIT:: Das grep ohne v lässt dann nur noch Zeilen durch die Kommentare sind.

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Cae » 11.11.2012 10:27:54

Liffi hat geschrieben:Wobei ich da im Moment noch ignoriere, dass vor den Kommentaren noch Whitespace sein darf.
Und Multilinekommentare im Stil /* foo
bar */
auch. Wobei das wiederum in Strings vorkommen koennte, wo es dann nicht matchen darf... klingt nach einer zukuenftigen entspannten awk-Sitzung.
Liffi hat geschrieben:"nested switch case if else" versuchen (falls das nicht dein englisches Äquivalent war).
Doch, das war es.
Liffi hat geschrieben:Bin mir aber nicht sicher, ob es den gibt. In der 'freien Natur' bin ich noch nie auf etwas derartiges gestoßen.
Ich wuerde mich auch nicht dafuer verbuergen, dass dieser Stil wirklich fuer irgendwas gut ist. In dem Zusammenhang habe ich auch mal ein paar Quelltexte vom Obfuscated C Contest [1] zu lesen versucht, aber da blickt ja kein Schwein mehr durch.

Gruss Cae

[1] http://ioccc.org/
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Liffi
Beiträge: 2345
Registriert: 02.10.2004 01:33:05

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Liffi » 11.11.2012 10:41:08

Cae hat geschrieben:
Liffi hat geschrieben:Wobei ich da im Moment noch ignoriere, dass vor den Kommentaren noch Whitespace sein darf.
Und Multilinekommentare im Stil /* foo
bar */
auch. Wobei das wiederum in Strings vorkommen koennte, wo es dann nicht matchen darf... klingt nach einer zukuenftigen entspannten awk-Sitzung.
Deshalb sollte man auch immer in den '/*'-Kommentaren jede Zeile mit * anfangen. Das ist tatsächlicher guter Stil und dient vor allem dem Vereinfachen von grep :-D.

Benutzeravatar
GoKi
Beiträge: 2068
Registriert: 04.07.2003 23:08:56
Lizenz eigener Beiträge: MIT Lizenz

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von GoKi » 11.11.2012 11:15:21

Ich würde sagen, dass es zwar erlaubter Code ist, er aber in dem Fall sinnlos ist.
Die Dokumentation der switch Anweisung besagt, dass der Kontrollfluss in den switch-Body springt und zwar abhängig von den dort definierten case Labels. Daraus folgere ich, dass jegliche Anweisungen, die außerhalb eines case steht einfach gar nicht ausgeführt wird, weil die Anweisungen übersprungen werden. Man kann an manchen Stellen also jeglichen Code platzieren, den man niemals ausführen will.
Ein sinnvoller Einsatz ist vielleicht, wenn man den Kontrollfluss nach dem Sprung zu einem case weiter kontrollieren will, z.B. sowas in der Art:

Code: Alles auswählen

#include "stdio.h"
int main(void) {
   switch (3) {
     printf("never printed\n");
     case 1:
       return 1;
       break;
     case 2:
       return 2;
       break;
     case 3:
       printf("3\n");
       if (0) {
         case 4:
           printf("4\n");
           break;
       } else {
         case 5:
           printf("5\n");
           break;
       }
       case 6:
         printf("6\n");
         break;
     default:
       return 42;
   }
   return 0;
}
MfG GoKi
:wq

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Cae » 11.11.2012 11:58:11

Aha, damit wuerde man das "Durchfallen ueber das Ende" (case ohne abschliessendes break) kontrollieren koennen.

Nehmen wir an, der Code bei 3: und bei 4: soll jeweils direkt von dem bei 5: gefolgt ausgefuehrt werden. Dann wuerde der 4:-Teil aus der Sicht von 3: uebersprungen werden; 4: wuerde direkt we zu 5: weiterlaufen.

Code: Alles auswählen

#include <stdio.h>

int main(void) {
	int i;
	
	for (i = 3; i < 6; i++) {
		printf(" * %d\n", i);
		switch (i) {
			case 3:
				puts("<- 3");
				if (0) {
			case 4:
					puts("<- 4");
				} else {
			case 5:
					puts("<- 5");
				}
				break;
			default:
				printf("!? %d\n", i);
				break;
		}
	}

	return 0;
}
Nur dummerweise funktioniert das nicht, 4: sieht irgendwie das else und macht dann Schluss:

Code: Alles auswählen

 * 3
<- 3
<- 5
 * 4
<- 4 # <-- *hier* sollte die 5 folgen
 * 5
<- 5
Wenn ich das } else { direkt nach die 5: schieben will, mosert der Compiler:

Code: Alles auswählen

casetest.c: In function ‘main’:
casetest.c:14:9: error: label at end of compound statement
und baut das Ding nicht.

Gruss Cae

--Edit: Man kann else { und } einfach weglassen, dann passiert das Erwartete. Aber das geht dann nur einmal, man kann es nicht so aneinanderreihen, wie ich es in Erinnerung habe.
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Benutzeravatar
GoKi
Beiträge: 2068
Registriert: 04.07.2003 23:08:56
Lizenz eigener Beiträge: MIT Lizenz

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von GoKi » 11.11.2012 12:42:13

Wenn Du bei 4 einen if Block betreten hast (auch wenn Du da einfach hinspringst), dann kannst Du danach nicht in den else Block weiter. Daher erscheint da dann auch keine 5. Schaut natürlich anders aus, wenn Du das else weglässt.
MfG GoKi
:wq

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Meillo » 12.11.2012 07:42:24

Cae hat geschrieben: vor einiger Zeit habe ich einen Code gelesen, wo ifs in einer bestimmten Art innerhalb eines switch-Statements verteilt waren. Nun weiss ich aber nicht mehr a) wie dieser Stil heisst, b) wie die Struktur aussieht oder c) ob es ueberhaupt C war.
Bist du dir sicher, dass es ifs waren? Oder meinst du vielleicht Duff's Device? http://en.wikipedia.org/wiki/Duff%27s_device
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Meillo » 12.11.2012 07:47:51

Cae hat geschrieben: Wenn ich das } else { direkt nach die 5: schieben will, mosert der Compiler:

Code: Alles auswählen

casetest.c: In function ‘main’:
casetest.c:14:9: error: label at end of compound statement
und baut das Ding nicht.
Ja, denn einem case muss ein Statement folgen.
Use ed once in a while!

Benutzeravatar
schorsch_76
Beiträge: 2601
Registriert: 06.11.2007 16:00:42
Lizenz eigener Beiträge: MIT Lizenz

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von schorsch_76 » 12.11.2012 08:44:50

Cae hat geschrieben: Wenn ich in den Kernel-Sourcen nach Zeilen mit if suche, die von case-Zeilen gefolgt werden, finde ich keine Strukturen dieser Art
Das glaub ich gern, denn was macht den ein switch[1] ? Es springt abhängig vom Wert der Kontrolvariable zum jeweiligen case. Wenn du dann die cases in Ifs einschliesst möchte man wohl abhängig von der if Abfrage Marken deaktiveren oder aktivieren, aber so funktioniert switch nicht. Auch allein für die Codewartbarkeit und Codeverständlichkeit würde ich das auf jeden Fall vermeiden. Selbst wenn das compiliert würde ich eher auf "funktionierendes undefiniertes Verhalten" schieben als das dass "guter definierter" C Code ist.

Du kannst innerhalb eines cases wieder komplette switch/if statemens bauen aber nicht über case Makren hinweg. Du kannst auch das "break" weglassen, dann wird der Code der im switch Statement folgt noch ausgeführt. Das ist auch definiert.

Code: Alles auswählen

int v1 = 1;
int v2 = 3;
switch (v1)
{
  case 1:
     printf("v1=1");
     switch (v2)
     {
       case 3:
         printf("v2=3");
       case 2: 
         printf("v2=2");
         break;
       default:
         printf("v2=unbekannt");
         break;
     }
     break;
 default:
    printf("v1=unbekannt");
    break;
}
Hier würde das folgende ausgegeben:

Code: Alles auswählen

v1=1
v2=3
v2=2
da bei v2/case 3 das break fehlt.

Just my two cents ;)

Gruß
schorsch

[1] http://en.wikipedia.org/wiki/C_syntax#S ... statements

Benutzeravatar
GoKi
Beiträge: 2068
Registriert: 04.07.2003 23:08:56
Lizenz eigener Beiträge: MIT Lizenz

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von GoKi » 12.11.2012 09:42:28

schorsch_76 hat geschrieben:Das glaub ich gern, denn was macht den ein switch[1] ? Es springt abhängig vom Wert der Kontrolvariable zum jeweiligen case. Wenn du dann die cases in Ifs einschliesst möchte man wohl abhängig von der if Abfrage Marken deaktiveren oder aktivieren, aber so funktioniert switch nicht. Auch allein für die Codewartbarkeit und Codeverständlichkeit würde ich das auf jeden Fall vermeiden. Selbst wenn das compiliert würde ich eher auf "funktionierendes undefiniertes Verhalten" schieben als das dass "guter definierter" C Code ist.
Als undefiniert würde ich es nicht bezeichnen, jedoch stimme ich dir ansonsten vollkommen zu. Solche Strukturen sollte man wirklich vermeiden.
MfG GoKi
:wq

Benutzeravatar
Meillo
Moderator
Beiträge: 9241
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Meillo » 12.11.2012 12:27:58

schorsch_76 hat geschrieben: Das glaub ich gern, denn was macht den ein switch[1] ? Es springt abhängig vom Wert der Kontrolvariable zum jeweiligen case. Wenn du dann die cases in Ifs einschliesst möchte man wohl abhängig von der if Abfrage Marken deaktiveren oder aktivieren, aber so funktioniert switch nicht.
Korrekt, denn case ist nur eine Marke, die zur Compilezeit (!) verarbeitet wird. Im compilierten Code bleiben nur Spruenge zu bestimmten Instruktionen uebrig, an denen kann man zur Laufzeit nichts mehr aendern.
Du kannst innerhalb eines cases wieder komplette switch/if statemens bauen aber nicht über case Makren hinweg.
Das stimmt so nicht ganz. In C sind die cases nur Marken, aber keine Bloecke. Switch ist in C nicht mehr als syntactic sugar fuer ein goto-Konstrukt. Ein zwischengefuegtes case unterbricht also keineswegs ein groesseres Konstrukt mit Blockstruktur. Das erwaehnte Duff's Device zeigt eben diesen Fall sehr schoen. (In der von dir verlinkten Erklaerung ist das sogar explizit beschrieben.)


In anderen Sprachen mag das anders sein. Und der Sinn von solchem Code ist eine ganz andere Diskussion.
Use ed once in a while!

Cae
Beiträge: 6349
Registriert: 17.07.2011 23:36:39
Wohnort: 2130706433

Re: C (?): bestimmte Verschachtelung von switch und if

Beitrag von Cae » 12.11.2012 17:58:19

Meillo hat geschrieben:Bist du dir sicher, dass es ifs waren? Oder meinst du vielleicht Duff's Device? http://en.wikipedia.org/wiki/Duff%27s_device
Bingo, 100 Punkte fuer dich. Genau das Ding meinte ich. Vielen Dank.

Natuerlich kann ich bei der Suche nach ifs keine Beispiele finden, da sie in diesem Aufbau nicht vorkommen... vermutlich hatte ich Pointer und Gleichsetzung rein optisch "irgendwas kurzes und was mit = danach" als if gespeichert. Es war naemlich damals (wie mir natuerlich erst jetzt wieder einfaellt) genau dieser Artikel in der englischen Wikipedia.
Immerhin die Tatsache, dass der {}-Block case-Sprungmarken mittendrin hatte, hat gestimmt, wobei sich ein feingliedriger Aufbau schon hier experimentell als undurchsichtig/unbrauchbar erwiesen hat.

Danke fuer's Mitraten. ;)

Gruss Cae
If universal surveillance were the answer, lots of us would have moved to the former East Germany. If surveillance cameras were the answer, camera-happy London, with something like 500,000 of them at a cost of $700 million, would be the safest city on the planet.

—Bruce Schneier

Antworten