LINUX.ORG.RU

Стиль switch - case

 ,


0

3

Увидел в http://www.linux.org.ru/forum/development/10302494 такой стиль:

    switch (event.type) {
        case SDL_QUIT: {
	    quit = 1;
        } break;
    }
Вопрос ко всем и к Bizun в частности.

В чем физический смысл такого «{...} break;»?

Я в этом вижу только яростную ненависть к goto. Господа, кто еще в мире пишет в таком стиле?

В каких open source проектах используют такой стиль программирования?

★★

Последнее исправление: fopen (всего исправлений: 1)

Человек тупо сделал ошибку не заметив свою скобку, а это уже стилем назвали. ::))

Dron ★★★★★
()

Скобочки как бы логическую структуру обозначают. Но смысла нет, да — отступов хватает.

Ненависти к goto я здесь не вижу. И вообще, goto надо использовать, когда он нужен!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Dron

А я завел отдельную тему, не про его ошибку, а про стиль программирования.

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

Там goto не нужно.

«{...} break;» делает switch чисто структурным программированием, в то время как оригинальный switch (это goto и кучка меток) таковым не является. Поэтому в таком применении swicth я усмотрел ненависть к goto.

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

Скобочки обозначают логическую структуру, но тем самым вводят в заблуждение, т. к. это расходится с логикой switch.

Про ненависть я мысль раскрыл в ответе Дрону. Стиль switch - case (комментарий)

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

Это всё мелочи реализации, есть переключатель switch им удобно переключать, есть goto им удобно прыгать. Два инструмента два применения, всё. В нюансах утопнешь, не заморачивайся.

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

Я уж не знаю, что там за ненависть может быть, но ставь скобки, не ставь скобки — все равно итоговая конструкция будет одной и той же!

Самый лучший switch — это когда по порядку идут проверки, тогда просто генерируется "массив" адресов перехода и на нужный делается goto. В общем же случае, ЕМНИП, результат будет такой же, как с кучей if

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Dron

Я не заморачиваюсь. Речь не про goto, не про применение switch. Речь про стиль программирования.

Я хочу знать: в каких открытых программах применяют такой стиль программирования. Кто знает? Дайте ссылок.

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

Ага.

if (...) {
    {
        {{{ bayan_on(); }}}
    }
}

ставь скобки, не ставь скобки — все равно итоговая конструкция будет одной и той же!

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

В чем физический смысл такого «{...} break;»?

Возможность объявления локальной для case переменной. Но в данном случае это лишняя хрень.

andreyu ★★★★★
()

В чем физический смысл

Самый очевидный - удобнее копипейстить/двигать код. break, скорее всего, должен оставаться на месте, т.ч. скобки ограничивают полезный контент. Например, понадобился код case-а в другом месте, «y%» и он уже в руках. Сравни с альтернативами.

DonkeyHot ★★★★★
()

я познаю мир

скобки как бы говорят компилятору: «забудь, что это происходит внутри switch... это просто кусок кода». в частности, это позволяет объявлять локальные переменные, избегать традиционных для switch ошибок, этсетера.

anonymous
()

Я в этом вижу только яростную ненависть к goto

switch..case это и есть практически goto, хотя многие об этом и не знают ;-)

пример по приведённом в топике коду:

    switch (event.type) {
        case SDL_QUIT: {
	    quit = 1;
            ..some code placed here..
            case WHAT_THE_FUCK: 
            ..more code..
        } break;
    }

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

Именно, что не все понимают. А такими скобками - это ссать против ветра. Твой пример хорош!

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

Скобки иногда нужны, чтобы вводить локальные переменные. А ставить их в одних местах и не ставить в других - сомнительный стиль. goto тут вообще ни при чем.

unsigned ★★★★
()

В switch/case используют {} обычно для того, чтобы переменные определять. Но тут конечно это немного не при чём.

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

switch..case это и есть практически goto, хотя многие об этом и не знают ;-)

Щито?
switch-case - это прямой аналог if-else if-else.

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

это и есть практически goto

Только от Duff's device компилятор расстраивается и генерирует код абы как. А если вести себя хорошо, то тут тебе и переход по таблице и дерево if'ов для больших switch-case.

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

Если такой стиль применять везде (а не только в некоторых местах), то глаз привыкнет и читать будет легче. А вообще, вкусовщина, сабж ещё [не]интереснее, чем споры про терминологию.

NeXTSTEP ★★
()

Скобочки позволяют вводить локальные переменные.

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

Щито?
switch-case - это прямой аналог if-else if-else.

может быть в php так оно и есть :-)

а вот в С, во первых непосредственно внутри блока switch могут быть выражения отличные от case, во вторых case может быть на любом уровне вложенности {} в том числе внутри if,while и for;

можешь считать что case просто задаёт метки «перехода по константному значению» в коде и выражение

switch(value) {
  expression1;
  case const_a: expression_a;break;
  case const_b: expression_b;
}

раскрывается в «лапшу» с if и goto:

/** псевдокод **/
// компилер делает таблицу переходов по меткам 
// или цепочку if..else if..else c переходами
if (value==const_a) goto label_a;
else if (value==const_b) goto label_b;
else goto label_default;
// а далее идёт простыня кода с расставленными по case метками
expression1;
label_a: expression_a; goto the_end;
label_b: expression_b;
label_default: default_expression;
the_end: 

далее к примеру

#include <stdio.h>
/* switch-case-default demo */
void scd(int c) {
	int t;
	t=3;
	printf("c=%d ",c);
	switch(c) {
		case 1: for(t=0;t<5;t++) {
			case 2:
			printf("t=%d",t);
			if (t<4) {
				default:
				putchar(',');
			}
		}
		break;
		case 3: printf("omitted");
	}
	putchar('\n');
}
int main() {
	int t;
	for(t=0;t<5;t++)
		scd(t);
	return 0;
}
вполне легальный и рабочий код на С, дающий следующий выхлоп:
c=0 ,t=4
c=1 t=0,t=1,t=2,t=3,t=4
c=2 t=3,t=4
c=3 omitted
c=4 ,t=4

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

+ да.

для примера если аргументы(опции) разное число но всегда в заданом порядке без пропусков то свитч хорош.

одна есть недостаток у свича есть лексема завершителя .

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

Не ну при чём тут пэхапэ. Просто никогда на такие извращения не натыкался, а в книжках именно switch-case как альтернатива предлагался.
Что сказать... век живи - век учись.

invy ★★★★★
()

В чем физический смысл такого «{...} break;»?

Ни какого, насколько я помню, компиляторы сишки переберают операторы до следующего case'a или break'a. Именно по этому, все варианты записей ниже валидны:

switch (arm) {
	case 123:
	break;
	
	case 321: {
	} break;
	
	case 120:
	case 180:
	break;
}
Еще, в зависимости от компилятора, в можно прыгать из одного кейса в другой. Вроде так.

Я в этом вижу только яростную ненависть к goto. Господа, кто еще в мире пишет в таком стиле?

Не уловил смысла. goto в нужных местах очень и очень выручает, например когда я патчил панельку, было место, в котором было что-то около 10 проверок разных. Так вот, там на много проще было использовать goto, чем кучу if'ов вложенных.

В каких open source проектах используют такой стиль программирования?

Если честно, не знаю, но думаю, что K&R style один из самых популярных. По крайней мере, мне он очень нравится, я его использую во всех Си-подобных языках.

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

Человек тупо сделал ошибку не заметив свою скобку, а это уже стилем назвали.

Не не, я действительно всегда так и пишу.

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

Скобочки обозначают логическую структуру, но тем самым вводят в заблуждение, т. к. это расходится с логикой switch.

Хм, интересное мнение. Но как по мне - вся суть switch'a выбрать некоторое действие исходня из одного значения. Как это нарушает логику конструкции?

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

Но в данном случае это лишняя хрень.

Для меня это логическое отделение куска кода, еще один уровень абстракции.

Для тебя может и хрень.

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

А вот эту «возможность» я в своем компиляторе убрал. Хз, может я преимуществ не вижу, но у меня бы ошибка вылетила при компиляции.

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

Ну, то есть, языка ты не знаешь, спецификацию не читал, но мнение все равно имеешь. Не стыдно?

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

Я не сильно придерживался стандарта. Выражения, да, старался максимально близко. А в остальном - копировал поведение, но без нюансов.

Да и вообще, я когда начал писать компилятор, по английски почти не читал, это в 16 лет было. Писал на гейм мейкере :) Это, наверное, самый фановый мой проект, надо его переписать на что то более серьезное или на самого же себя :)

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

Ты некомпетентен и туп. Case - это аналог меток, посмотри на Duff device, хотя бы.

В нормальных компиляторах - именно так. Те, кто на коленке пишет/писал могут и преобразовывать в некое подобие if/else последовательности. Но оно не такое гибкое, как класический switch.

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

Для меня это логическое отделение куска кода, еще один уровень абстракции.

Оно уже и так логически выделено с помощью case/break.

Для тебя может и хрень.

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

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

Почему не стыдно. Стыдно. Так облажался, имея при этом немаленький опыт писанины на C и C++.

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

Текст должен быть удобен для чтения, а не для редактирования

Следует, однако, заметить, что в отличии от порнухи, чтение текста программ производится именно с целью его модификации, а не ради эстетического или ещё какого удовольствия. Т.ч. балланс между читаемостью и редактируемостью определяется уровнем незнания кода, а не национальностью.

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

Чушь. В большинстве случаев код читается с целью понимания, а не модификации. Вот когда закончишь детский сад, отучишься в школе, пойдешь на свою первую работу, проведешь там лет 5 джуниором, начнут тебя допускать под строгим присмотром до более-менее серьезных задач, тогда и поймешь, что код 99% времени читают, и менее 1% времени пишут.

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

Порядок кейсов не важен. Возможны два случая:

  1. значения кейсов располагаются достаточно плотно друг к другу, тогда генерируется таблица адресов перехода
  2. значения кейса разбросаны слишком сильно, в таком случае компилятор генерирует бинарный поиск по ключам.

Критерий выбора 1) или 2) зависит от компилятора, в clang было ИМХО, что кейсы покрывают 60% диапазона между минимальным и максимальным (т.е. в таблице переходов будет 40% дырок).

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

что кейсы покрывают 60% диапазона между минимальным и максимальным (т.е. в таблице переходов будет 40% дырок).

Эм, «минимальыми и максимальными» - чем? И что такое дырки?

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

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

ну вот есть у тебя switch по unsigned int x, со значениями в case V1, V2, ... Vn

тогда в случае таблицы переходов tbl реализация будет goto tbl[x-min(V1...Vn)], понятно, что если max(V1...Vn)-min(V1....Vn) > n-1, то в таблице будут неиспользуемые адреса (дырки) и если их будет слишком много, то копилятор вместо таблицы будет выполнять бинарный поиск.

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

Огого, чет я ни чего не понял. Допустим, исходная конструкция:

unsigned int x;

switch (x) {
    case V1: break;
    case V2: break;
    case V3: break;
    ...
    case VN: break;
}

//Таблица будет прирмерно такая:
V1, adr1
V2, adr2
V3, adr3
...
VN, adrN
Вот. Если элементов мало, то можно просто перебирать таблицу в цикле от первого к последнему элементу, и все. Если она большая, то да, двоичный поиск очень уместен. Но что такое goto «tbl[x-min(V1...Vn)]»? Разве значения-константы (x (условно), V1...Vn) накладывают какие то ограничения на использование того или иного алгоритма поиска значения в таблице? Ну и к " max(V1...Vn)-min(V1....Vn) > n-1" вопрос тот же.

Возможно, я сильно туплю, но все же... Да, туплю, ниже описал.

UPD: Я, кажется, понял что такое goto tbl[x-min(V1...Vn)]. Это некая большая таблица, в которой x-min(V1...Vn) - будет адрес куска исполняемого кода, верно?

Я, если честно, под таблицей предпологал другую структуру (ключ1, адрес1 ... ключN, адресN) и в своемнедо-компиляторе сделал именно так. При выполнении свитча просто перебирались константы и при совпадении ключей совершался переход.

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

UPD2: использование бинарного поиска при условии «max(V1...Vn)-min(V1....Vn) > n-1» обуславливается экономией памяти, не так ли?

UPD3: В общем, я разобрался :)

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

Да-да, я так и понял :)

Вся эта путаница произошла из за того, что я изучал исходники не нормального компилятора, а SmallC. Там, для экономии памяти, был просто список (ключ, адрес), и все.

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