Случайный охват шкафа

Просмотрев некоторый сторонний код C, я наткнулся на что-то вроде:

switch (state) { case 0: if (c=='A') { // open brace // code... break; // brace not closed! case 1: // code... break; } // close brace! case 2: // code... break; } 

Который в коде, который я просматривал, оказался просто опечаткой, но я был удивлен, что он скомпилирован с ошибкой.

Почему это действительно C?
Каков эффект на выполнение этого кода по сравнению с закрытием скобки в ожидаемом месте?
Есть ли случаи, когда это может быть полезно?

Изменить: В примере, на котором я смотрел, все перерывы присутствовали (как указано выше), но ответ также может включать в себя поведение, если разрыв отсутствует в случае 0 или 1.

Мало того, что это действительно так, аналогичная структура использовалась в реальном коде, например, Duff’s Device , который является развернутым циклом для копирования буфера:

 send(to, from, count) register short *to, *from; register count; { register n = (count + 7) / 8; switch(count % 8) { case 0: do { *to = *from++; case 7: *to = *from++; case 6: *to = *from++; case 5: *to = *from++; case 4: *to = *from++; case 3: *to = *from++; case 2: *to = *from++; case 1: *to = *from++; } while(--n > 0); } } 

Поскольку оператор switch действительно просто вычисляет адрес и переходит к нему, легко понять, почему он может перекрываться с другими структурами управления; линии в других структурах управления имеют адреса, которые также могут быть нацелены на достижение цели!

В случае, если вы представили, представьте, не было ли в вашем коде switch или break . Когда вы закончите выполнение той части инструкции if , вы просто продолжаете идти, поэтому вы попадете в case 2: Теперь, поскольку у вас есть switch и break , важно то, что break может вырваться из. Согласно странице MSDN, «Операция C break» ,

Оператор break прекращает выполнение ближайшего вложения do , for , switch или while, в котором он появляется. Элемент управления переходит к оператору, который следует за завершающим оператором.

Поскольку ближайший вложенный оператор do , for , switch или while является вашим коммутатором (обратите внимание, что если он не включен в этот список), то, если вы находитесь внутри блока then , вы переходите к внешней стороне оператора switch . Что еще более интересно, это то, что произойдет, если вы введете case 0 , но c == 'A' – false. Затем, if управление передачей происходит сразу после закрывающей скобки then блока, и вы начинаете выполнение кода в case 2 .

В C и C ++ законно прыгать в циклы и блокировать до тех пор, пока вы не перепрыгнете через какие-либо объявления переменных. Вы можете проверить этот ответ для примера с помощью goto , но я не понимаю, почему одни и те же идеи не будут применяться к блокам switch .

Семантика отличается от того, что } была выше case 1 как и следовало ожидать.
Этот код на самом деле говорит, что если state == 0 и c != 'A' перейдите к case 2 так как в этом случае закрывающая скобка оператора if . Затем он обрабатывает этот код и обрабатывает оператор break в конце кода кода case 2 .

Interesting Posts
Давайте будем гением компьютера.