#c #switch #case
Привет. Пытаясь ответит на один из вопросов здесь, с удивлением обнаружил, что следующий код #includeint main() { int a = 123; const char *r = "initial value"; switch (a) { case 1: r = "1"; break; if (0) { default: r = "not 1"; } } puts(r); return 0; } нормально компилируется GCC и выдает при исполнении not 1 Мне кажется, что код явно с такой ошибкой, что даже компилироваться не должен. В чем тут дело?
Ответы
Ответ 1
Тело switch (как и тело while, do/while, for и т.п) это просто statement, в котором мы расставляем метки case и default, и в котором возможно использование break. Не более того. Метки case и default могут появляться только внутри statement, принадлежащего какому-то switch, но в остальном ограничения, накладываемые на расстановку этих меток, ничем не отличаются от любых других меток. Аналогичным образом передача управления на эти метки происходит по правилам, похожим на правила goto, с той только разницей, что передать управление на метку case и default может только ее непосредственно охватывающий switch. В вашем случае, если заменить метки case и default на "обычные" метки, мы получим просто составной statement { l1: r = "1"; break; if (0) { l2: r = "not 1"; } } Ничего необычного в этом составном statement-е нет. Положение меток в нем не нарушает никаких правил языка. В том, что метка default: передает управление внутрь ветки некоего if, нет ничего необычного. Вас никто не заставляет даже использовать именно составной statement для реализации тела switch, т.е. вопреки распространенной практике тело switch не обязательно должно быть заключено в {}. Вы можете воспользоваться любым другим типом statament и расставить метки в нем int i = rand() % 4; switch (i) if (0) case 0: printf("Privet!\n"); else if (0) case 1: printf("Hello!\n"); else if (0) case 2: printf("World!\n"); else default: printf("Ku-ku!\n"); Обратите внимание, что эта замечательная техника написания switch избавляет вас от необходимости помнить о break в конце каждой ветки.Ответ 2
код явно с такой ошибкой, что даже компилироваться не должен В коде нет никаких синтаксических ошибок, почему он не должен компилироваться? А с точки зрения логики обработки switch получается так: if( a == 1 ) goto label_case_1; else goto label_default; label_case_1: r = "1"; goto case_end; if(0) { /* этот if никак не влияет на видимость метки */ label_default: r = "not 1"; } case_end: puts(r);
Комментариев нет:
Отправить комментарий