LINUX.ORG.RU

C++, switch, case ... что-то я туплю

 ,


0

3

Редко пользуюсь оператором switch, хотя думал, что знаю как он работает. Обычно я обязательно пользуюсь break, и switch тогда работает ожидаемо. Но вот я сделал примитивный пример, в котором не могу понять что происходит.

#include <iostream>

using namespace std;

int main (int argc, char *argv[]) 
{
    int i=0;

    switch (i)
    {
    	case 0  : { std::cout << "0"; }
        case 1  : { std::cout << "1"; }
      	default : { std::cout << "D"; }
    }

    return 0;
}


Что выведет этот пример?

Вначале я думал что «0».

Потом не смог найти внятного описания default - выполняется ли это условие только если не подошло ничего из остального, или просто выполняется если до него дошло дело. Я склонился к тому, что default выполняется просто если до него дошло дело (небыло никаких break). Поэтому результат должен быть «0D».

На деле на gcc результат будет таким: «01D».

Два вопроса в связи с этим:

- С какого перепугу в результате затесалось 1?
- Как же все-таки должно срабатывать default?

★★★★★

Последнее исправление: Xintrea (всего исправлений: 2)
Ответ на: комментарий от anonymous

Хз, у меня printf отрабатывает.
Не понятно(точнее не прозрачно) другое, почему i объявленным считается(причём только объявленным, значение не присваивается) если эта строка не исполняется.

anonymous
()
Ответ на: комментарий от Deleted

Я так понимаю, человек задаётся вопросом «Почему так, а не эдак?»

Изначально ТС был просто не в курсе, зачем в switch-case используют break. Совсем не в курсе. Всё время просто повторял увиденную конструкцию. А теперь решил всё-таки выяснить, но оказалось, что switch-case работает совсем не так, как он это себе представлял.

И вместо того, чтобы прочитать описание этого самого switch-case, создал на форуме тему, где написал код и свои ожидания от этого кода. Что-то в духе:

я делаю

i = 0;
i = 3;
Почему-то после этого i равно трём. Разве оно не должно быть нулю? Какого хрена i = 3; исполняется? Я же написал i = 0;.

Ему непонятно, почему так происходит, а остальным непонятно, как это может быть непонятно.

i-rinat ★★★★★
()
Ответ на: комментарий от Dudraug

Тут идет скачок через инициализацию. В с++ такое не скомпилтся вообще .

Ты думаешь я не проверял?

anonymous
()
Ответ на: комментарий от i-rinat

Непонятно, почему он не наткнулся на это раньше. Мой первый раз был в 16 лет. Тогда я не знал зачем break в switch, но ставил ибо так в примерах везде.

Кто-то сейчас мог бы позлорадствовать. Но мы все воспитанные. Я допустим не знал кое что про числа с плавающей точкой...

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от Xintrea

в ядре линукса полно такого кода, всё замечательно

Harald ★★★★★
()
Ответ на: комментарий от anonymous

Не понятно(точнее не прозрачно) другое, почему i объявленным считается(причём только объявленным, значение не присваивается) если эта строка не исполняется.

Это локальная переменная, под нее память выделяется на стеке всегда (если собирать без оптимизации). Код инициализации может не отработать.

anonymous
()
Ответ на: комментарий от Dudraug

У меня собирается как gcc7, так и g++7, но printf() не вызывается никогда, даже если его заменить на puts("hello");. Возможно, сильно зависит от версии компилятора и 7-ка учитывает UB даже без оптимизации.

anonymous
()
Ответ на: комментарий от Dudraug

Когда и какие конструкторы генерирует компилятор. Это не матан, конечно, но разбираться приходится...

Deleted
()
Ответ на: комментарий от i-rinat

Ему непонятно, почему так происходит, а остальным непонятно, как это может быть непонятно.

При этом ТС, если читал внимательно, в этой теме смог узнать сильно больше, чем написано в документации. А «иксперты», которым все понятно, почесали свое ЧСВ, понтанулись, понадували пузырей и так и ушли, не узнав ничего нового. И вот тут реально не понятно чё приходили? Но ты продолжай свое RTFM, твое мнение очень важно для нас.

anonymous
()
Ответ на: комментарий от Xintrea

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

Есть места, где это наоборот полезное поведение и устраняет потенциальные ошибки, кстати.

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от i-rinat

Ну а ты чего пришёл? Что-то новое сказал?

Расписал duff's device, так что даже школьнику понятно. Написал про fallthrough.

А ты че пришел? Какая от тебя польза, кроме понтов?

anonymous
()
Ответ на: комментарий от i-rinat

Ты издеваешься, что ли?! Там всё в деталях описано, с примерами.

Да, в деталях, не спорю. С примерами, как положено. А смысл не написан.

Написано, что выполнение проваливается

Написано.

есть пример кода и его результата исполнения.

Есть и пример. Смысла нету.

Причём, описано это несколько раз.

Хоть двести раз, смысла это не добавит.

Xintrea ★★★★★
() автор топика

default вроде всегда выполняется, когда не было break

xmikex ★★★★
()
Ответ на: комментарий от Deleted

Повторюсь: в нете я нашел (в своё время, ссылок не дам) только
несколько примеров «годного» применения проваливания в нору.
Я так понимаю, человек задаётся вопросом «Почему так, а не эдак?»

Да, я хочу понять почему решили сделать такую конструкцию. При том, что к тому времени в структурном программировании уже огульно хаяли метки и переходы по меткам.

Xintrea ★★★★★
() автор топика
Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от Xintrea

Смысла нету.

Какой тебе смысл то нужен? Ты хочешь понять для чего так сделали? Для того, чтобы можно было

case A:
case B:
...code...
break;

или

case A:
...some A specific code....
case B:
... common for A и B....
break;

Второй вариант конечно более опасный и его надо бы снабжать комментарииями, ну или избегать. Но первый вполне юзабельный и встречается часто. Да и стейт-машина тут особо не при чем. Какой тебе еще смысл надо? Тебе в первых сообщениях сказали, что это более цивилизованный goto.

Dudraug ★★★★★
()
Ответ на: комментарий от Xintrea

Да, я хочу понять почему решили сделать такую конструкцию. При том, что к тому времени в структурном программировании уже огульно хаяли метки и переходы по меткам.

Оно так и в С# работает, который гораздо моложе сишки. Потому что это позволяет писать эффективный и наглядный код.

Dudraug ★★★★★
()
Ответ на: комментарий от anonymous

Расписал duff's device, так что даже школьнику понятно.

Это ты с вершины своего ЧСВ определил, что понятно? Чем ты тогда отличаешься от остальных, которых решил порицать?

А ты че пришел? Какая от тебя польза, кроме понтов?

Ух, какой ты крутой.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Изначально ТС был просто не в курсе, зачем в switch-case используют break. Совсем не в курсе.

Ты что-то путаешь. Вопрос был в том, что ТС не в курсе как вообще switch-case работает без break.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Ээээ, повторю: С помощью дальнейшего прохода можно выстроить логику, основанную на вхождении. Жаль, я потерял примеры. Было очень разжевано. На этом много построено. Короче - доролнительные финты.

Deleted
()
Ответ на: комментарий от Xintrea

Изначально ТС был просто не в курсе, зачем в switch-case используют break. Совсем не в курсе.

Ты что-то путаешь. Вопрос был в том, что ТС не в курсе как вообще switch-case работает без break.

А это не одно и то же?

i-rinat ★★★★★
()
Ответ на: комментарий от Deleted

Эээ, ну например так:

case: lalala
case: lalala2
case: lalala3; break;
case: lalalan и т.д.
Deleted
()
Ответ на: комментарий от i-rinat

А это не одно и то же?

Конечно, нет. Смотри: что мы знаем о break? Что когда код до него дойдет, будет прыг на конец switch. Большего нам знать и не нужно, тут все однозначно.

Теперь убираем break из switch, и получаем вопрос ТС.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Что когда код до него дойдет, будет прыг на конец switch

Из чего элементарно логически выводится, что когда НЕ будет брейка, то НЕ будет прыга на конец switch. А выполнение провалится в следующие кейсы. Так в чем был исходный вопрос тогда? Объясните мне основы логики - так?

curufinwe ★★★★★
()
Ответ на: комментарий от Xintrea

Теперь убираем break из switch, и получаем вопрос ТС.

Да, блин, вопроса ТС-а не возникло бы, если бы ТС прочитал хотя бы один вменяемый учебник по C. Ну или по C++.

eao197 ★★★★★
()
Ответ на: комментарий от Xintrea

При том, что к тому времени в структурном программировании уже огульно хаяли метки и переходы по меткам.

Огульно хаят только троли и школьники. Взрослые разработчики понимают, что у меток и goto, как у любого инструмента ограниченная ниша, где их имеет смысл использовать. Более того, если со временем появляется инструмент лучше - используют его. А «огульно хаяли» - значит нашли тему поболтать. Нужно это только балаболам. Стоит только поднять тему типа goto, глобальных переменных, макросов - тут же набегут толпы и начнут поливать все это толстым слоем сам знаешь чего. При том что у всего этого есть своя сфера применения.

В таких случаях, нужно уметь из потока болтовни добывать крупицы пользы (которой там может и не быть).

anonymous
()
Ответ на: комментарий от eao197

если бы ТС прочитал хотя бы один вменяемый учебник по C. Ну или по C++.

Можно учебник по Go читать. Там написано что-то типа: в отличие от Си, тут не нужно break, потому что выполнение не проваливается, как в Си.

i-rinat ★★★★★
()
Ответ на: комментарий от curufinwe

Из чего элементарно логически выводится, что когда НЕ будет брейка, то НЕ будет прыга на конец switch. А выполнение провалится в следующие кейсы. Так в чем был исходный вопрос тогда? Объясните мне основы логики - так?

По сути, да. Посмотри название темы.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Теперь убираем break из switch, и получаем вопрос ТС.

И вопроса никакого нет, если автор выучил бы базовый синтаксис си или си++ или c# или яве. В этих языках(да и во многих других) свич-кейс работает ОДИНАКОВО.

Dudraug ★★★★★
()
Ответ на: комментарий от Dudraug

Вот кстати нет, в C# малость сделали работу над ошибками, там провала в case нет.

Про эффективность - сомнительно. Пригождается слишком редко, а ошибки порождает часто, так что даже костыль [[fallthrough]] прикрутили (не прошло и 30 лет). И лучше бы этот редкий случай покрывался отдельно, хотя бы с помощью goto.

Ну и про наглядность я надеюсь что ты пошутил. Это хуже чем goto, фактически вычисляемый goto в обертке совсем другой, безопасной конструкции «или-или» (которую и сделали в C#, и которая емнип в паскале).

anonymous
()
Ответ на: комментарий от curufinwe

Он почему то думал, что если не будет брейка, то будет переход в default. Как до такого можно дойти... ну я даже не представляю

Dudraug ★★★★★
()
Ответ на: комментарий от i-rinat

Это ты с вершины своего ЧСВ определил, что понятно?

Давай по конструктиву. Чё тебе не понятно в моем объяснении с примером того, как работает duff's device.

Ух, какой ты крутой.

Хочешь померяться у кого длиннее. Мое объяснение того, что switch/case - это переход по меткам длиннее и понятнее твоего (C++, switch, case ... что-то я туплю (комментарий)). А твое понятно только тому, кто и так уже все знает... Ну, а сначала ответить на вопрос ТС, а потом начать на него бочку катить, типа что он ничего не понимает - это вообще хрень.

Можешь начинать рефлексировать.

anonymous
()
Ответ на: комментарий от Xintrea

Смотри

Я никак не могу следить за твоей мыслью, потому что стадия, в которой мне было непонятно, что такое switch-case и зачем там break, была очень давно. Я даже не помню, удивлялся я этому, или узнал сразу.

Помню, что очень удивился, когда узнал что Duff's device на русский переводят как «устройство Даффа», хотя по смыслу это «трюк Даффа». Видимо, слово device настолько крепко ассоциируется с устройствами, что переводящие и помыслить не могли, что у него есть ещё значения.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

А это не одно и то же?

case с телом, но без break на практике обычно ошибка. Так что разница между ваще не знал, или не знал мелкий нюанс никому нафиг не нужный огромна. И состоит она в том, сможет он писать работающий код или код-ревьюер начнет кипятком писать при виде такого кода.

anonymous
()
Ответ на: комментарий от Xintrea

Теперь убираем break из switch, и получаем вопрос ТС.

До чего чувака довели. Он уже начал про себя писать в третьем лице.

anonymous
()
Ответ на: комментарий от Dudraug

Он почему то думал, что если не будет брейка, то будет переход в default.

Давай, не будем приписывать мне того, чего я не говорил.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Давай по конструктиву. Чё тебе не понятно в моем объяснении с примером того, как работает duff's device.

Я уже знаю, как он работает. И точно помню, что когда его увидел, не понял, почему у этого подхода есть своё имя. Потому что там всё было вполне себе очевидно. Поэтому на мне нельзя проверить понятность объяснения.

Мое объяснение того, что switch/case - это переход по меткам длиннее и понятнее твоего

Чем длиннее, тем понятнее? Бред какой-то пошёл уже.

Можешь начинать рефлексировать.

Спасибо, нет.

i-rinat ★★★★★
()
Ответ на: комментарий от Xintrea

Давай, не будем приписывать мне того, чего я не говорил.

Ты в оп посте описал поведение именно такое.

Dudraug ★★★★★
()
Ответ на: комментарий от anonymous

Ну и про наглядность я надеюсь что ты пошутил.

Хз, никогда не было проблем с чтением провалов в case в си.

Dudraug ★★★★★
()
Ответ на: комментарий от eao197

Я так понимаю, что все тут отметившиеся эксперты разбираются во всех нюансах C/C++ и многих других упомянутых языков (Go, C#, яве, чё еще забыл).

Как зайдешь на LOR, так сразу понимаешь ничтожность своего существования. Тут, блин, даже с помощью логики выводят семантику языка.

anonymous
()
Ответ на: комментарий от anonymous

Про эффективность - сомнительно. Пригождается слишком редко, а ошибки порождает часто, так что даже костыль [[fallthrough]] прикрутили (не прошло и 30 лет). И лучше бы этот редкий случай покрывался отдельно, хотя бы с помощью goto.

Чёт я не понял, а как тогда в тех языках обрабатывают широко распространенный случай, когда case 1, case 2 и case 3 нужно обработать одинаково? Или там не проваливаются только если для case есть тело?

Вообще в C++ для случая провала есть предупреждение компилятора...

anonymous
()
Ответ на: комментарий от i-rinat

Duff's device на русский переводят как «устройство Даффа», хотя по смыслу это «трюк Даффа».

Вообще-то, «метод Даффа».

anonymous
()

Кста, в теме как-то вскользь не обсудили нужность фигурных скобок после case.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.