Ich lief auf dieses Problem ein, und eines Tages entschied ich mich dazu zu graben.
Die kurze Nicht-Antwort, aber pragmatische Lösung:
Ein Weg, um dieses „Problem“ zu arbeiten, ist ein Semikolon zu verwenden, ;
, direkt nach dem Doppelpunkt einer case ...:
Aussage. Zum Beispiel mit dem Beispiel, das Sie zur Verfügung gestellt, kann es „fixiert“ werden, so kompiliert und verhält sich wie Sie intuitiv es erwarten würde:
case 1:; // <- Note semi-colon.
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.delegate = self;
Die lange Antwort:
Einige Geschichte: Früher C nur erlaubte es Ihnen, zu Beginn eines Blocks "block local" Variablen zu deklarieren, denen dann verschiedene Anweisungen folgten. C99 hat Dinge geändert, so dass Sie variable Deklarationen und Anweisungen frei mischen können.
Im Kontext der C99 BNF-Grammatik ist eine Variablendeklaration eine und eine Anweisung ist eine statement
. A statement
bedeutet mehrere Dinge, von denen einer als compound-statement
bekannt ist, der der bekannte { ... }
Block ist.Der ...
Teil ist lose definiert als zero or more
block-items
mit block-item
lose als either a
declaration
or a
statement
definiert ist.
Das Problem liegt in der Art und Weise ein labeled-statement
(a goto Etikett, case label oder default:
im wesentlichen die ...:
Anweisungen) definiert ist, die lose ...: zero or more
statements
definiert ist. Es ist nicht, wie man intuitiv erwarten könnte, zero or more
statements
or
declarations
. Die Verwendung eines ;
direkt nach dem labeled-statement
s :
beendet im Wesentlichen den zero or more
statements
Teil eines labeled-statement
. Dies führt dazu, dass die Grammatik auf die compound-statement
Definition zurückfällt, was ermöglicht, dass die nächste "Anweisung" entweder eine statement
oder ist.
Ich habe nicht untersucht, ob dies ein unbeabsichtigtes Übersehen der C99-Sprachspezifikation ist (in der Praxis ein Fehler im C99-Standard), oder ob dies eine pragmatische Zugeständnis an die Komplexität des Schreibens von Grammatiken ist . Wenn Sie mit dem Schreiben von Grammatiken nicht vertraut sind, werden Sie feststellen, dass die obige Erklärung eine Rekursion ermöglicht: A labeled-statement
kann case 1: case 2: case 3:
entsprechen. Zu vereinfachende Begriffe (1)
, einige Arten von Grammatik Rekursion sind einfach und "unzweideutig", während andere komplex und "mehrdeutig" sind. Der Einfachheit halber behandeln die meisten Sprachwerkzeuge nur den Fall, bei dem eine Mehrdeutigkeit deterministisch gelöst werden muss, indem man sich nichts anderes als "das nächste Token" ansieht. Ich erwähne das nur deshalb, weil dies zwar intuitiv als ein Mangel in der C99-Spezifikation erscheint, es aber zwingende, nicht offensichtliche Gründe dafür gibt ... und ich habe mir keine Mühe gegeben, weitere Untersuchungen zu diesem Thema durchzuführen, um das herauszufinden in jedem Fall.
(1)
Dies ist keine technisch genaue Beschreibung, aber eine angemessene Annäherung für diejenigen, die nicht mit den damit verbundenen Problemen vertraut sind.
EDIT:
Die Lösung, die ich Werke gab in „die meisten“ Fällen (Fälle „Nutzungen“ zu sein, nicht switch
case
s), aber es ist in einem Fall fehlschlagen: Das wird nicht funktionieren, wenn die Deklaration deklariert ein C99 variable length array
, wie case 1:; void *ptrs[count];
Dies liegt daran, in C99 ist es ein Fehler zu "überspringen" die Deklaration eines C99 VLA, die in demselben lexikalischen Bereich ist, in dem der Sprung stattfand. In diesen Fällen müssen Sie case 1: { void *ptrs[count]; }
verwenden. In diesem Fall endet der Umfang des VLA ptrs
bei der Schlussmelde }
. Das ist komplizierter, als es zuerst erscheint, da die folgende vollkommen legal C-Code ist, obwohl auf den ersten Blick würde man intuitiv denken, es ist nicht:
switch(3){
case 0:
printf("case 0\n");
break;
case 1:;
int *ip = NULL;
printf("case 1\n");
break;
case 2:
{
int ia[6];
printf("case 2\n");
break;
case 3:
printf("case 3\n");
break;
default:
printf("default\n");
}
}
Dies kompiliert, und wenn ausführen, druckt case 3
.
Siehe auch: manchmal Wikipedia: Duffs Device
+1 Sie können jedoch, wenn Sie verschachtelten Bereich erstellen, mithilfe von {...} die Anweisungen für eine Fallbezeichnung umbrechen. –