Ich habe eine Situation, in der ich möchte, dass zwei Fälle in einer C ++ - switch-Anweisung beide zu einem dritten Fall durchfallen. Insbesondere würde der zweite Fall bis zum dritten Fall durchfallen , und der erste Fall würde auch bis zum dritten Fall durchfallen, ohne den zweiten Fall zu durchlaufen.
Ich hatte eine blöde Idee, habe es versucht und es hat funktioniert! Ich wickelte den zweiten Fall in einem if (0) {
... }
. Es sieht aus wie das:
#ifdef __cplusplus
# include <cstdio>
#else
# include <stdio.h>
#endif
int main(void) {
for (int i = 0; i < 3; i++) {
printf("%d: ", i);
switch (i) {
case 0:
putchar('a');
// @fallthrough@
if (0) { // fall past all of case 1 (!)
case 1:
putchar('b');
// @fallthrough@
}
case 2:
putchar('c');
break;
}
putchar('\n');
}
return 0;
}
Wenn ich es ausführe, erhalte ich die gewünschte Ausgabe:
0: ac
1: bc
2: c
Ich habe es sowohl in C als auch in C ++ versucht (beide mit Clang), und es hat das Gleiche getan.
Meine Fragen sind: Ist das C / C ++ gültig? Soll es tun, was es tut?
c++
c
if-statement
switch-statement
language-lawyer
Mark Adler
quelle
quelle
switch(x) { case A: case B: do_this(); if(x == B) also_do_that(); ... }
. Das war auch, IMO, schrecklich. Bitte schreiben Sie solche Dinge einfach so aus, als ob Anweisungen, auch wenn dies bedeutet, dass Sie eine Zeile an zwei Stellen wiederholen müssen. Verwenden Sie Funktionen und Variablen (und Dokumentation!), Um das Risiko einer versehentlichen späteren Aktualisierung an nur einer Stelle zu verringern.Antworten:
Ja, das ist erlaubt und macht was du willst. Für eine
switch
Anweisung lautet der C ++ - Standard :Wenn die
if
Anweisung ausgewertet wird, wird der Kontrollflussif
unabhängig von den dazwischen liegenden Fallbezeichnungen gemäß den Regeln einer Anweisung fortgesetzt.quelle
Ja, das soll funktionieren. Die Fallbezeichnungen für eine switch-Anweisung in C entsprechen fast genau den goto-Bezeichnungen (mit einigen Einschränkungen hinsichtlich der Funktionsweise verschachtelter switch-Anweisungen). Insbesondere definieren sie selbst keine Blöcke für die Anweisungen, die Sie als "innerhalb des Falls" betrachten, und Sie können sie verwenden, um in die Mitte eines Blocks zu springen, wie Sie es mit einem goto könnten. Beim Springen in die Mitte eines Blocks gelten die gleichen Einschränkungen wie bei goto hinsichtlich des Springens über die Initialisierung von Variablen usw.
In der Praxis ist es wahrscheinlich klarer, dies mit einer goto-Anweisung zu schreiben, wie in:
switch (i) { case 0: putchar('a'); goto case2; case 1: putchar('b'); // @fallthrough@ case2: case 2: putchar('c'); break; }
quelle
bee
(im C-Modus; in C ++ wird der Fehler "Kann nicht von der switch-Anweisung zu diesem Fall springen / Sprung umgeht die Variableninitialisierung").goto
die sauberere Lösung verwenden.goto
ist sehr bösartig, aber es ist wirklich nichts zu beanstanden, wenn Sie nicht manuell komplexe Kontrollstrukturen daraus machen. Bei dem ganzen "Goto als schädlich angesehen" ging es darum, HLL-Code (z. B. C) zu schreiben, der aussieht, als würde er von einem Compiler ausgegeben (jmps überall hin und her). Es gibt viele gut strukturierte Verwendungen von goto wie "Nur vorwärts" (konzeptionell nicht anders alsbreak
oder frühreturn
), "Nur Wiederholungsschleife" (vermeidet die Verschleierung des gemeinsamen Flusspfads und kompensiert das Fehlen verschachteltercontinue
) usw.Wie andere Antworten bereits erwähnt haben, ist dies nach dem Standard technisch zulässig, für zukünftige Leser des Codes jedoch sehr verwirrend und unklar.
Aus diesem Grund
switch ... case
sollten Anweisungen normalerweise mit Funktionsaufrufen und nicht mit viel Inline-Code geschrieben werden.switch(i) { case 0: do_zero_case(); do_general_stuff(); break; case 1: do_one_case(); do_general_stuff(); break; case 2: do_general_stuff(); break; default: do_default_not_zero_not_one_not_general_stuff(); break; }
quelle
do_general_stuff
standardmäßig ist, sondern nur für Fall 2 (und 0 und 1). Der Schalter wird jedoch niei
außerhalb des Bereichs 0..2 ausgeführt.do_general_stuff
standardmäßig ist, sondern nur für Fall 2 (und 0 und 1).general
unddefault
verschiedene Wörter waren. OTOH, es ist eine bekannte Tatsache, dass Menschen normalerweise immer noch ein Wort lesen können, wenn die mittleren Buchstaben verschlüsselt sind. Wir neigen dazu, den Anfang und das Ende zu betrachten, daher ist es wahrscheinlich nicht ideal für die Skimmbarkeit, wenn nur die Mitte unterschiedlich ist. Entfernen Sie möglicherweise dasdo_
Präfix.