Страница 1 из 2
goto в С++.
Добавлено: Ср сен 21, 2011 15:17:44
Pika4u
Пишу программы для компьютера. На С++. Раньше ещё немного знал асм для АВР. И меня заинтересовало, есть ли в С++ метки и команды перехода по метке. Оказывается, есть. Эта команда называется goto. Но я прочитал про неё много нелестных отзывов в интернете. Ну не знаю, мне так легче меток понаставить, чем городить кучу циклов. Хотя на компиляцию программы с goto уходит дольше времени-секунд 7. Кто что думает?)
Re: goto в С++.
Добавлено: Ср сен 21, 2011 15:27:08
Satyr
Фигня, longjmp() пользуй

Re: goto в С++.
Добавлено: Ср сен 21, 2011 15:38:21
Vov123
между С и С++ очень большая разница и вам как новичку надо наплевать на предрассудки опытных программистов.Пишите как вам удобно,потом разберётесь-нужно вам "goto" или нет.
Re: goto в С++.
Добавлено: Ср сен 21, 2011 15:40:49
Pika4u
Satyr писал(а):Фигня, longjmp() пользуй

Сейчас попробую)) longjmp()-в скобках что писать?)) это тоже самое, что goto?)))
Re: goto в С++.
Добавлено: Ср сен 21, 2011 18:30:05
Pika4u
Прочитал в гугле про лонгджамп-не понравилось. гото проще)))
Re: goto в С++.
Добавлено: Ср сен 21, 2011 18:37:14
Мастер Ломастер
если в программе меньше 24 меток и меньше 32 goto на них из разных мест - это не программа, а срамота. никогда так не пишите - засмеют все!
Re: goto в С++.
Добавлено: Ср сен 21, 2011 18:38:34
Psych
Vov123 писал(а):Пишите как вам удобно,потом разберётесь-нужно вам "goto" или нет.
+1
Нет ничего такого.
Re: goto в С++.
Добавлено: Ср сен 21, 2011 18:56:40
Pika4u
Re: goto в С++.
Добавлено: Ср сен 21, 2011 21:33:18
Errorkpi
goto работает замечательно, но с этим оператором сложно читать код.
Дедушка Вирт доказал, что любой код можно написать на простейши логических конструкциях без гото...
В общем вердикт: если удобно гото - пользуйте, но старайтесь свести его применение к минимуму. С и С++ имеет достаточно прозрачные механизмы (например return не в конце функции, как обычно, а по условию и в любом месте где удобно; или циклы do... while) написания программ без гото. В конце концов вы сами дойдете до момента когда не захотите использовать гото.
Re: goto в С++.
Добавлено: Ср сен 21, 2011 21:55:45
Dr. Alex
Вообще-то по правилам хорошего тона, оператор GOTO неиспользуется в языках высокого уровня. Но, как говорится, если очень хочется, но нельзя, то - можно

. Главное не переусердствовать
Я для себя его не использую. Просто пишу процедурку или функцию. И всё...
Re: goto в С++.
Добавлено: Чт сен 22, 2011 04:44:37
Pika4u
В принципе, если сделать нормальные комментарии, то можно и не запутаться. Да и если пишешь прогу для себя, то хоть об"goto"йся))
Re: goto в С++.
Добавлено: Чт сен 22, 2011 09:56:58
SergeBS
Pika4u писал(а):В принципе, если сделать нормальные комментарии, то можно и не запутаться. Да и если пишешь прогу для себя, то хоть об"goto"йся))
Угу. Вот только когда через месяц-два захочется прогу подправить, то выяснится - легче по новой написать, чем разобраться в goto из 10 разных мест в одно с расстояния от 10 до 1000 строчек.
В Инете полно книжек о ПРАВИЛЬНЫХ приемах программирования. И правильные приемы - они потому и правильные, что экономят усилия. Лучше сразу их усвоить, чем потом переучиваться.
Мне понравилась "ВЕРЕВКА ДОСТАТОЧНОЙ ДЛИНЫ, ЧТОБЫ ВЫСТРЕЛИТЬ СЕБЕ В НОГУ.
Правила программирования на С и С++." Ален И. Голуб
Хотя с другой стороны "Обходя не наступая разложенные грабли теряешь возможность приобрести практический опыт"

Re: goto в С++.
Добавлено: Чт сен 22, 2011 10:01:23
SergeBS
Vov123 писал(а):между С и С++ очень большая разница и вам как новичку надо наплевать на предрассудки опытных программистов.Пишите как вам удобно,потом разберётесь-нужно вам "goto" или нет.
Да-да!! Даешь изобретение велосипеда! С квадратными колесами! потому что круглые колеса - это предрассудки опытных механиков.

Re: goto в С++.
Добавлено: Чт сен 22, 2011 12:38:12
Errorkpi
Помню в универе я долго холиварил с одним С (не С++) кодером, который любил goto, и не верил в работу программ без него.
Все применение этого оператора в его коде сводилось к прерыванию цикла (не доходя до конца счета, или переход на следующую итерацию), и выход из функции при различных условиях (где не применим глобальный IF, например по нажатию на кнопку на неопределенной итерации бесконечного цикла (BorlandC3.11) ).
Вот так мы и холиварили, я писал break, continue и return var, а он goto lable и все тут.
Re: goto в С++.
Добавлено: Чт сен 22, 2011 16:10:17
SergeBS
Errorkpi писал(а):
Вот так мы и холиварили, я писал break, continue и return var, а он goto lable и все тут.
Если пишешь ты на Си
Будь хоть трижды ламер
Про такого говорят:
"Он крутой програмер"
(с) Неизвестный пасквилянт ( ПАСКвилянт от pascal, и соответственно есть и наСИльники - от С)
Отмазка - мне по большому счету пофигу, что C/C++. что Pascal/Delphi. Переключаться конечно тяжко. Но возможно.
Re: goto в С++.
Добавлено: Чт сен 22, 2011 19:38:30
SfS
О Go To и предрассудках. ИМХО, основанное на десятилетнем опыте разработки...
Наверное нет программистского или околопрограммистского форума, на котором не поднимался бы холивар о GOTO.
Одни (таких мало) говорят - "GOTO" есть хорошо, "GOTO" можно и нужно всегда использовать. Ведь так просто перейти куда надо и сделать что хочешь.
Другие, особенно читавшие много теории и мало практиковавшие - при виде "GOTO" визжат как насилуемые девственницы. Один такой писал "я не могу видеть эту мерзость. это говно. это уродство".
Но ведь - всё хорошо в меру. И всё хорошо по назначению. Гвозди молотком надо забивать, а шурупы отвёрткой вкручивать. Наоборот - плохо получается.
Итак - что хорошего в GoTo? Хорошо есть то, что можно (теоретически) перейти откуда и куда угодно. Но это в общем случае код запутывает. Ибо у каждой функции в идеале - одна точка входа и одна - выхода.
Писать вообще без GoTo можно, но иногда - это самое GoTo очень помогает сократить и УПРОСТИТЬ код на С. Например, если есть многоэтапная проверка:
Код: Выделить всё
int f(){
// 1й этап работы
if (условие1){
init_1();
}
else goto error1;
// 2й этап работы
if (условие2){
init_2();
}
else goto error2;
// 3й этап работы
if (условие3){
init_3();
}
else goto error3;
// Всё ОК, выходим
return(0);
// Действия по завершению при ошибке на этапе 3
error3:
done_3();
// Действия по завершению при ошибке на этапе 2
error2:
done_2();
// Действия по завершению при ошибке на этапе 1
error1:
done_1();
// Ошибка, выходим
return(-1);
}
Разумеется, этот код можно написать и без GoTo. Но, тогда не избежать вложенных условий или доп. переменных или того и другого.
И пусть меня утопят в нечистотах, если этот код не читаем или непонятен.
Кстати, подобыный код часто встречается при инициализации устройств.
Для себя я выработал несколько критериев использования GoTo на С.
1. Использовать GoTo можно только в пределах одной функции.
2. Если очень тянет сделать переход из одной функции внутрь другой, то значит программа плохо спроектирована и тот кто её проектировал нуждается во внушении терморектальным методом.

В общем нужно переразбить программу на функции по-другому.
3. Использовать GoTo нужно ТОЛЬКО тогда, когда это резко улучшает читабельность программы и сокращает её код.
4. НЕ использовать GoTo для организации циклов и выхода из цикла (на С есть for, while, break).
В итоге - GoTo встречается в моих программах не часто, но лишь оно уместно.
Может, всё, что я написал покажется многим очевидным, а может кому и пригодится.
Re: goto в С++.
Добавлено: Пт сен 23, 2011 08:38:04
SergeBS
SfS писал(а):О Go To и предрассудках. ИМХО, основанное на десятилетнем опыте разработки...
ИМХО, основанное на 30-летнем опыте разработки...
Одни (таких мало) говорят - "GOTO" есть хорошо, "GOTO" можно и нужно всегда использовать. Ведь так просто перейти куда надо и сделать что хочешь.
Другие, особенно читавшие много теории и мало практиковавшие - при виде "GOTO" визжат как насилуемые девственницы. Один такой писал "я не могу видеть эту мерзость. это говно. это уродство".
Писать вообще без GoTo можно, но иногда - это самое GoTo очень помогает сократить и УПРОСТИТЬ код на С. Например, если есть многоэтапная проверка:
В итоге - GoTo встречается в моих программах не часто, но лишь оно уместно.
Может, всё, что я написал покажется многим очевидным, а может кому и пригодится.
Кое-что покоцал - чтобы короче было...
ИМХО - пригодится начинающим однозначно! Чтобы на пустом месте войн не затевали.
Изложено вполне разумно. В общем и целом согласен. Поскольку у медиков есть фразочка: "Все - лекарство, все - яд. Разница в дозировке."
Насчет примера немного дополню
Альтернатива №1:
switch - case - и никаких доп. переменных в простейшем случае.
Альтернатива №2
Вообще-то функция инициализации возвращает код завершения (код ошибки). Т.е. идеологически правильнее
Код: Выделить всё
int f(){
// 1й этап работы
// что-то делаем, а затем
if (условие1) // условие ошибки 1
{
return ErrCode1;
}
// 2й этап работы
// что-то делаем, а затем
if (условие2) // условие ошибки 2
{
return ErrCode2;
}
...
return 0;
}
Примерно так. При этом проще отлаживать и добавлять/убирать проверки, т.е. приспосабливать к конкретному случаю.
НО! Код из примера SfS тоже имеет право на существование, поскольку ДЕЙСТВИТЕЛЬНО может оказаться лучше по части ресурсов, читаемости и т.п.
Зависит от кучи деталей. Т.е. я всего лишь изложил, как МОЖНО (но это не значит, что НУЖНО) избавиться от goto. Всего лишь альтернативное решение.
Еще раз повторю на всякий случай: все 3 варианта (goto, switch, return ErrCode) имеют право на существование. Какой лучше - зависит от задачи (и опыта программиста) .
ЗЫ: начинающим goto лучше избегать. Поскольку либо без него НУЖНО обойтись, либо задачка - не для начинающих. Остальное - крайне редко.

Re: goto в С++.
Добавлено: Пт сен 23, 2011 10:53:50
avreal
В общеми и целом согласен. Так, дополнения и «вкусовые» обсуждения.
SfS писал(а):Но ведь - всё хорошо в меру. И всё хорошо по назначению. Гвозди молотком надо забивать, а шурупы отвёрткой вкручивать. Наоборот - плохо получается.
Какая-от из старинных программ «оценки исходников» пыталась выдать некий «коэффициент качества», базируясь на % комментариев в коде, на количестве пустых строк (просто пустая строка, разделяющая логически-связные кусочки, иногда лучше комментаряи) и т.д. Всё в том же духе «всё есть яд и всё есть лекарство, зависит от дозы».
Так она-то начинала гразно ругаться, если видела много goto, но если их вообще не было, она тоже снижала балл. По мнению автора программы, парочка goto на тысячу строк кода -- нормально, если меньше, значит где-то перемудрили с вложенными if-ами, которые читать так же трудно
SfS писал(а):Ибо у каждой функции в идеале - одна точка входа и одна - выхода.
Во! В идеале точка выхода тоже
одна. Что несколько снижает ценность советов заменить кучу goto такой же кучей точек выхода из функции

Хотя если хоть того, хоть другого много, значит таки надо ещё подумать над структурой.
SfS писал(а):Писать вообще без GoTo можно, но иногда - это самое GoTo очень помогает сократить и УПРОСТИТЬ код на С. Например, если есть многоэтапная проверка:
...
Разумеется, этот код можно написать и без GoTo. Но, тогда не избежать вложенных условий или доп. переменных или того и другого.
И пусть меня утопят в нечистотах, если этот код не читаем или непонятен.
Единственное -- на мой вкус -- лучше уход по проблеме ставить в прямой ветви if. Мне так легче читается. Сравните:
Код: Выделить всё
if (all_ok) {
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
} else { // тут после разбора кода выше ещё надо вспомнить, от какого условия else
goto error;
}
и
Код: Выделить всё
if (!all_ok) {
goto error;
}
// Собственно, else уже и не нужно
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
many_many_lines_of_code;
Соответственно, Ваш пример перепишется так:
Код: Выделить всё
int f2()
{
if (!cond1()) goto error1;
init1();
if (!cond2()) goto error2;
init2();
if (!cond3()) goto error3;
init3();
return 0;
error3:
done3();
error2:
done2();
error1:
done1();
return -1;
}
Re: goto в С++.
Добавлено: Пт сен 23, 2011 11:04:38
avreal
SergeBS писал(а):НО! Код из примера SfS тоже имеет право на существование, поскольку ДЕЙСТВИТЕЛЬНО может оказаться лучше по части ресурсов, читаемости и т.п.
По большому счёту -- что дальше, то важнее именно читаемость. А ресурсы... Компиляторы-то всё грамотнее. Правда от этого проблемы у начинающих, компилятор ухватил суть кода («да нифига этот код полезного не делает») и выбросил всё
Перепишем обсуждаемый пример так:
Код: Выделить всё
#define BREAKABLE_BLOCK \
for( uint8_t _breakable_block_ = 1; _breakable_block_ ; _breakable_block_ = 0)
int8_t f3()
{
uint8_t level = 0;
BREAKABLE_BLOCK {
if (!cond1()) break;
init1();
++level;
if (!cond2()) break;
init2();
++level;
if (!cond3()) break;
init3();
++level;
}
switch (level) {
case 3:
return 0;
case 2: done3();
case 1: done2();
case 0: done1();
return -1;
}
}
Тут и временная переменная, и switch...
Скомпилируем avr-gcc -std=c99 -O2 -S -mmcu=atmega8 goto.c
И получим код, который
совпадает с исходным вариантом из if (cond1() ) { init1(); } else { goto error1; }.
Код: Выделить всё
f3:
/* prologue: function */
/* frame size = 0 */
rcall cond1
tst r24
breq .L2
rcall init1
rcall cond2
tst r24
breq .L3
rcall init2
rcall cond3
tst r24
breq .L4
rcall init3
ldi r24,lo8(0)
ret
.L4:
rcall done3
.L3:
rcall done2
.L2:
rcall done1
ldi r24,lo8(-1)
ret
Компилятор прекрасно допёр, что переменная level растворяется в структуре кода и убрал её. Равно как и переменную в for(;;) в макросе.
При -Os код немного хуже, что-то там оптимизатор недоделал и вышло в конце такое
Код: Выделить всё
rcall init3
ldi r24,lo8(0)
ret
.L3:
rcall done2
.L2:
rcall done1
ldi r24,lo8(-1)
ret
.L4:
rcall done3
rjmp .L3
Так что если пишущий хорошо сам понимает, что он делает, то и компилятор его поймёт.
SergeBS писал(а):ЗЫ: начинающим goto лучше избегать. Поскольку либо без него НУЖНО обойтись, либо задачка - не для начинающих. Остальное - крайне редко.

+100500
Как было написано в одной хорошей книжке по цифровой схемотехнике (рассчитанной ещё на, обобщённо говоря, «155-тую серию»)
Однако этот приём не следует рекомендоавть начинающим разработчикам, так как у них темперамент превалирует над опытом.
Сначала нужно научиться работать без «этого приёма», а со временем станет ясно, где он действительно к месту.
p.s. У меня goto мало, не в каждой программе даже. Как-то обходится в большинстве случаев.
Но и нет старания «обойтись без, бо низя».
Да, огороды в духе того BREAKABLE_BLOCK тоже не использую. Просто и так могу написать для демонстрации. И, как видите -- компилируется во вполне нормальный код

Re: goto в С++.
Добавлено: Пт сен 23, 2011 14:39:51
Errorkpi
avreal писал(а):#define BREAKABLE_BLOCK \
Мда....
Господин знает толк в извращениях.....
