Всегда полагал, что семантика switch/case/case/... аналогична if/if/if/... без break-а и if/else if/else if/... c break-ом. А тут решил не ставить break "в конце ветки выбора", и опля — сюрприз. Так что, товарищи, кто еще так же, как и я, заблуждался, будьте внимательны:
switch(1)
{
case 1 : cout << '1'; // prints "1",case 2 : cout << '2'; // then prints "2"
}
switch(1)
{
case 1 : cout << '1'; break; // prints "1" and exits the switchcase 2 : cout << '2'; break;
}
p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?
Здравствуйте, _hum_, Вы писали:
__>Всегда полагал, что семантика switch/case/case/... аналогична if/if/if/... без break-а и if/else if/else if/... c break-ом. А тут решил не ставить break "в конце ветки выбора", и опля — сюрприз. Так что, товарищи, кто еще так же, как и я, заблуждался, будьте внимательны: __>
__>switch(1)
__>{
__> case 1 : cout << '1'; // prints "1",
__> case 2 : cout << '2'; // then prints "2"
__>}
__>
__>
__>switch(1)
__>{
__> case 1 : cout << '1'; break; // prints "1" and exits the switch
__> case 2 : cout << '2'; break;
__>}
__>
__>p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?
Что тут не очевидного ?
switch(1) {
case 1:
case 2:
case 3:
case 4:
std::cout << '1';
default: break;
}
// prints 1
Здравствуйте, _hum_, Вы писали:
__>Всегда полагал, что семантика switch/case/case/... аналогична if/if/if/... без break-а и if/else if/else if/... c break-ом. А тут решил не ставить break "в конце ветки выбора", и опля — сюрприз. Так что, товарищи, кто еще так же, как и я, заблуждался, будьте внимательны: __>
__>switch(1)
__>{
__> case 1 : cout << '1'; // prints "1",
__> case 2 : cout << '2'; // then prints "2"
__>}
__>
__>
__>switch(1)
__>{
__> case 1 : cout << '1'; break; // prints "1" and exits the switch
__> case 2 : cout << '2'; break;
__>}
__>
__>p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?
Ясно зачем. Чтобы выполнить одинаковое действие для более одного значения проверяемой переменной.
Например так:
switch(x) {
case 1:
case 2:
printf("x <= 2");
break;
case 3:
printf("x = 3");
break:
default:
printf("x > 3");
break:
}
Здравствуйте, xobotik, Вы писали:
X>Здравствуйте, _hum_, Вы писали:
X>Что тут не очевидного ? X>
X>switch(1) {
X> case 1:
X> case 2:
X> case 3:
X> case 4:
X> std::cout << '1';
X> default: break;
X>}
X>// prints 1
X>
неочевидно то, что case срабатывает не постоянно, а только один раз. то есть, это не условие входа в ветку, идущую после case (как можно было бы подумать), а некий аналог метки для перехода по goto из switch:
Здравствуйте, SaZ, Вы писали:
SaZ>Здравствуйте, _hum_, Вы писали:
__>>...
SaZ>Ещё можно вот так.
ну так, если switch на деле — это завуалированный goto с динамическим выбором метки перехода, то тогда понятно, почему такие извраты на его основе появляются — фактически идет программирование на ассемблере.
Здравствуйте, BulatZiganshin, Вы писали:
BZ>Здравствуйте, _hum_, Вы писали:
__>>p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?
BZ>case 1: case 2: ....
"case" — переводится как "случай", и естественная человеческая семантика подразумевает "в случае, если значение в switch совпадает cо значением случая, выполнить то, что стоит после воеточия". а на деле же:
switch(3)
{
case 1: // пропускает, ибо 1 != 3case 2: // пропускает, ибо 2 != 3case 3: // входит, ибо 3 == 3case 4: // wtf?? 4!=3, а он все равно входитcase 5: // wtf?? 5!=3, а он все равно входит
};
и именно потому, что семантика не естественная: case на самом деле означает не предусловие, а метку, куда должен перейти поток управления из точки switch.
Здравствуйте, _hum_, Вы писали:
__>"case" — переводится как "случай", и естественная человеческая семантика подразумевает "в случае, если значение в switch совпадает cо значением случая, выполнить то, что стоит после воеточия". а на деле же: __>
__>switch(3)
__>{
__> case 1: // пропускает, ибо 1 != 3
__> case 2: // пропускает, ибо 2 != 3
__> case 3: // входит, ибо 3 == 3
__> case 4: // wtf?? 4!=3, а он все равно входит
__> case 5: // wtf?? 5!=3, а он все равно входит
__>};
__>
__>и именно потому, что семантика не естественная: case на самом деле означает не предусловие, а метку, куда должен перейти поток управления из точки switch.
Семантика в отрыве от break; конечно будет не естественная, да и пример switch, который Вы написали, не часто встречается на практике.
Здравствуйте, _hum_, Вы писали:
__>Всегда полагал, что семантика switch/case/case/... аналогична if/if/if/... без break-а и if/else if/else if/... c break-ом. А тут решил не ставить break "в конце ветки выбора", и опля — сюрприз. Так что, товарищи, кто еще так же, как и я, заблуждался, будьте внимательны:
О сколько нам открытий чудных чудо открытий принесёт.
__>p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?
Потому что не тем местом думали, когда язык делали. А потом этот бред во все прочие сишкообразные языки потащили. Потому что люди — тупые.
Только не надо про вот это "раз в год таки нужно протекание сквозь ветку", на это "раз в год" могли бы придумать вставку слова continue например.
Правка: перечисления в кейсах нужны, но для них можно было сделать более вменяемую реализацию без таких вот сюрпризов. Например
case 1,3,5..8 :
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, BulatZiganshin, Вы писали:
BZ>Здравствуйте, _hum_, Вы писали:
__>>p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?
BZ>case 1: case 2: ....
Для этого нафиг не нужна такая ублюдочная семантика. Если бы в кейсах можно было ставить диапазоны и перечисления, то это бы покрыло этот случай.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, _hum_, Вы писали:
__>неочевидно то, что case срабатывает не постоянно, а только один раз. то есть, это не условие входа в ветку, идущую после case (как можно было бы подумать), а некий аналог метки для перехода по goto из switch: __>
Тут немного иначе нужно думать, немного другими абстракциями.
Есть набор состояний, допустим S = { State1, State2, ... , StateN }
Есть регистр (R), который содержит текущее состояние.
На группу состояний S' — подгруппа S, или на одно любое состояние из S
есть набор инструкций или одна инструкция.
После завершения работы инструкций, выходим из обработки состояний или продолжаем работу.
В принципе если представить такими абстракциями, то более понятно все будет.
Здравствуйте, xobotik, Вы писали:
X>Здравствуйте, _hum_, Вы писали:
__>>неочевидно то, что case срабатывает не постоянно, а только один раз. то есть, это не условие входа в ветку, идущую после case (как можно было бы подумать), а некий аналог метки для перехода по goto из switch: __>>
X>Тут немного иначе нужно думать, немного другими абстракциями. X>Есть набор состояний, допустим S = { State1, State2, ... , StateN } X>Есть регистр (R), который содержит текущее состояние. X>На группу состояний S' — подгруппа S, или на одно любое состояние из S X>есть набор инструкций или одна инструкция. X>После завершения работы инструкций, выходим из обработки состояний или продолжаем работу. X>В принципе если представить такими абстракциями, то более понятно все будет.
и вы, серьезно, считаете это "естественной семантикой"
Здравствуйте, xobotik, Вы писали:
X>Здравствуйте, _hum_, Вы писали:
__>>"case" — переводится как "случай", и естественная человеческая семантика подразумевает "в случае, если значение в switch совпадает cо значением случая, выполнить то, что стоит после воеточия". а на деле же: __>>
__>>switch(3)
__>>{
__>> case 1: // пропускает, ибо 1 != 3
__>> case 2: // пропускает, ибо 2 != 3
__>> case 3: // входит, ибо 3 == 3
__>> case 4: // wtf?? 4!=3, а он все равно входит
__>> case 5: // wtf?? 5!=3, а он все равно входит
__>>};
__>>
__>>и именно потому, что семантика не естественная: case на самом деле означает не предусловие, а метку, куда должен перейти поток управления из точки switch.
X>Семантика в отрыве от break; конечно будет не естественная, да и пример switch, который Вы написали, не часто встречается на практике.
так поэтому я и обратил на эту штуку внимание только сейчас, после долгих лет знакомства, ибо всегда и всюду автоматом включался break, который делал семантику естественной. а тут решил сэкономить в угоду читабельности, и на тебе — "все, что вы знали о switch — неправда" . потому и предупреждаю других граждан
Здравствуйте, T4r4sB, Вы писали:
TB>Здравствуйте, BulatZiganshin, Вы писали:
BZ>>Здравствуйте, _hum_, Вы писали:
__>>>p.s. Вопрос к знатокам — зачем такая неочевидная и "техническая" семантика?
BZ>>case 1: case 2: ....
TB>Для этого нафиг не нужна такая ублюдочная семантика. Если бы в кейсах можно было ставить диапазоны и перечисления, то это бы покрыло этот случай.
Здравствуйте, _hum_, Вы писали:
X>>Тут немного иначе нужно думать, немного другими абстракциями. X>>Есть набор состояний, допустим S = { State1, State2, ... , StateN } X>>Есть регистр (R), который содержит текущее состояние. X>>На группу состояний S' — подгруппа S, или на одно любое состояние из S X>>есть набор инструкций или одна инструкция. X>>После завершения работы инструкций, выходим из обработки состояний или продолжаем работу. X>>В принципе если представить такими абстракциями, то более понятно все будет.
__>и вы, серьезно, считаете это "естественной семантикой"
Смотря что считать естественной семантикой.
Если есть goto, label и switch case break default.
То наверно не стоит одно с другим мешать.
P.S. Х... тоже гвозди можно забивать, но никто этого не делает.
Здравствуйте, _hum_, Вы писали:
__>и вы, серьезно, считаете это "естественной семантикой"
Можно, наверно, спросить у автора, почему оно так.
Как мне думается, были рассмотрены всевозможные варианты разбора ветвлений, самый часто используемый был реализован самым простым синтаксисом. Нормально же?
Здравствуйте, xobotik, Вы писали:
X>Здравствуйте, _hum_, Вы писали:
X>>>Тут немного иначе нужно думать, немного другими абстракциями. X>>>Есть набор состояний, допустим S = { State1, State2, ... , StateN } X>>>Есть регистр (R), который содержит текущее состояние. X>>>На группу состояний S' — подгруппа S, или на одно любое состояние из S X>>>есть набор инструкций или одна инструкция. X>>>После завершения работы инструкций, выходим из обработки состояний или продолжаем работу. X>>>В принципе если представить такими абстракциями, то более понятно все будет.
__>>и вы, серьезно, считаете это "естественной семантикой"
X>Смотря что считать естественной семантикой. X>Если есть goto, label и switch case break default. X>То наверно не стоит одно с другим мешать.
X>P.S. Х... тоже гвозди можно забивать, но никто этого не делает.
естественная — та, что естественна для человека, читающего программу. если написано if(a > 0) then print("positive integer"), то даже человек, первый раз читающий эту конструкцию, догадается о ее семантике. теперь проделайте то же самое со switch/case — угу.
Здравствуйте, CEMb, Вы писали:
CEM>Здравствуйте, _hum_, Вы писали:
__>>и вы, серьезно, считаете это "естественной семантикой"
CEM>Можно, наверно, спросить у автора, почему оно так. CEM>Как мне думается, были рассмотрены всевозможные варианты разбора ветвлений, самый часто используемый был реализован самым простым синтаксисом. Нормально же?
самый часто используемый — это выбор из альтернатив, то есть swith/case-break.
Здравствуйте, _hum_, Вы писали:
__>естественная — та, что естественна для человека, читающего программу. если написано if(a > 0) then print("positive integer"), то даже человек, первый раз читающий эту конструкцию, догадается о ее семантике. теперь проделайте то же самое со switch/case — угу.
Если брать пример Ваш:
switch (1) {
case 1: std::cout << '1';
case 2: std::cout << '2';
}
Что тут не естественного?
В Вашей некой системе состояние 1, интерпретируется как:
1) выполнение двух инструкций std::cout << '1'; std::cout << '2';
2) Или как ошибка, потому что забыли break;
В случае один — Вы немного криво пишите, лучше написать
switch (1) {
case 1:
case 2:
std::cout << '1';
std::cout << '2';
}