goto в С++.

Вопросы настройки, программирования, прошивки микроконтроллеров и микросхем программируемой логики
Аватара пользователя
Pika4u
Поставщик валерьянки для Кота
Сообщения: 2064
Зарегистрирован: Пт апр 24, 2009 11:39:16
Откуда: г.Оренбург

goto в С++.

Сообщение Pika4u »

Пишу программы для компьютера. На С++. Раньше ещё немного знал асм для АВР. И меня заинтересовало, есть ли в С++ метки и команды перехода по метке. Оказывается, есть. Эта команда называется goto. Но я прочитал про неё много нелестных отзывов в интернете. Ну не знаю, мне так легче меток понаставить, чем городить кучу циклов. Хотя на компиляцию программы с goto уходит дольше времени-секунд 7. Кто что думает?)
Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
Аватара пользователя
Satyr
Друг Кота
Сообщения: 7439
Зарегистрирован: Чт ноя 04, 2010 01:56:36
Откуда: г. Москва

Re: goto в С++.

Сообщение Satyr »

Фигня, longjmp() пользуй :))
Vov123
Опытный кот
Сообщения: 804
Зарегистрирован: Чт мар 12, 2009 16:31:05

Re: goto в С++.

Сообщение Vov123 »

между С и С++ очень большая разница и вам как новичку надо наплевать на предрассудки опытных программистов.Пишите как вам удобно,потом разберётесь-нужно вам "goto" или нет.
Аватара пользователя
Pika4u
Поставщик валерьянки для Кота
Сообщения: 2064
Зарегистрирован: Пт апр 24, 2009 11:39:16
Откуда: г.Оренбург

Re: goto в С++.

Сообщение Pika4u »

Satyr писал(а):Фигня, longjmp() пользуй :))

Сейчас попробую)) longjmp()-в скобках что писать?)) это тоже самое, что goto?)))
Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
Аватара пользователя
Pika4u
Поставщик валерьянки для Кота
Сообщения: 2064
Зарегистрирован: Пт апр 24, 2009 11:39:16
Откуда: г.Оренбург

Re: goto в С++.

Сообщение Pika4u »

Прочитал в гугле про лонгджамп-не понравилось. гото проще)))
Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
Мастер Ломастер
Поставщик валерьянки для Кота
Сообщения: 1995
Зарегистрирован: Ср май 11, 2011 21:37:45
Откуда: Цветочный город
Контактная информация:

Re: goto в С++.

Сообщение Мастер Ломастер »

если в программе меньше 24 меток и меньше 32 goto на них из разных мест - это не программа, а срамота. никогда так не пишите - засмеют все!
битва с дураками проиграна, победители торжествуют. слава победителям!
Аватара пользователя
Psych
Опытный кот
Сообщения: 848
Зарегистрирован: Ср мар 02, 2011 07:47:39
Откуда: Уфа

Re: goto в С++.

Сообщение Psych »

Vov123 писал(а):Пишите как вам удобно,потом разберётесь-нужно вам "goto" или нет.

+1
Нет ничего такого.
Аватара пользователя
Pika4u
Поставщик валерьянки для Кота
Сообщения: 2064
Зарегистрирован: Пт апр 24, 2009 11:39:16
Откуда: г.Оренбург

Re: goto в С++.

Сообщение Pika4u »

Мастер Ломастер писал(а):если в программе меньше 24 меток и меньше 32 goto на них из разных мест - это не программа, а срамота. никогда так не пишите - засмеют все!

:))) :))) :))) :))) У меня пока одна метка и один goto. Но будет расширяться))
Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
Аватара пользователя
Errorkpi
Встал на лапы
Сообщения: 102
Зарегистрирован: Вт мар 22, 2011 22:31:01

Re: goto в С++.

Сообщение Errorkpi »

goto работает замечательно, но с этим оператором сложно читать код.
Дедушка Вирт доказал, что любой код можно написать на простейши логических конструкциях без гото...
В общем вердикт: если удобно гото - пользуйте, но старайтесь свести его применение к минимуму. С и С++ имеет достаточно прозрачные механизмы (например return не в конце функции, как обычно, а по условию и в любом месте где удобно; или циклы do... while) написания программ без гото. В конце концов вы сами дойдете до момента когда не захотите использовать гото.
Аватара пользователя
Dr. Alex
Это не хвост, это антенна
Сообщения: 1438
Зарегистрирован: Вт окт 28, 2008 09:00:18
Откуда: Украина, Харьков
Контактная информация:

Re: goto в С++.

Сообщение Dr. Alex »

Вообще-то по правилам хорошего тона, оператор GOTO неиспользуется в языках высокого уровня. Но, как говорится, если очень хочется, но нельзя, то - можно :) . Главное не переусердствовать :write:
Я для себя его не использую. Просто пишу процедурку или функцию. И всё...
Порой мне кажется, что я делаю какое-то дерьмо, но когда я вижу, что делают другие, то я чувствую себя гением...
Аватара пользователя
Pika4u
Поставщик валерьянки для Кота
Сообщения: 2064
Зарегистрирован: Пт апр 24, 2009 11:39:16
Откуда: г.Оренбург

Re: goto в С++.

Сообщение Pika4u »

В принципе, если сделать нормальные комментарии, то можно и не запутаться. Да и если пишешь прогу для себя, то хоть об"goto"йся))
Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: goto в С++.

Сообщение SergeBS »

Pika4u писал(а):В принципе, если сделать нормальные комментарии, то можно и не запутаться. Да и если пишешь прогу для себя, то хоть об"goto"йся))

Угу. Вот только когда через месяц-два захочется прогу подправить, то выяснится - легче по новой написать, чем разобраться в goto из 10 разных мест в одно с расстояния от 10 до 1000 строчек.
В Инете полно книжек о ПРАВИЛЬНЫХ приемах программирования. И правильные приемы - они потому и правильные, что экономят усилия. Лучше сразу их усвоить, чем потом переучиваться.
Мне понравилась "ВЕРЕВКА ДОСТАТОЧНОЙ ДЛИНЫ, ЧТОБЫ ВЫСТРЕЛИТЬ СЕБЕ В НОГУ.
Правила программирования на С и С++." Ален И. Голуб
Хотя с другой стороны "Обходя не наступая разложенные грабли теряешь возможность приобрести практический опыт" :)
Человек - это звучит гордо, а обезьяна - объективно...
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: goto в С++.

Сообщение SergeBS »

Vov123 писал(а):между С и С++ очень большая разница и вам как новичку надо наплевать на предрассудки опытных программистов.Пишите как вам удобно,потом разберётесь-нужно вам "goto" или нет.

Да-да!! Даешь изобретение велосипеда! С квадратными колесами! потому что круглые колеса - это предрассудки опытных механиков. :)))
Человек - это звучит гордо, а обезьяна - объективно...
Аватара пользователя
Errorkpi
Встал на лапы
Сообщения: 102
Зарегистрирован: Вт мар 22, 2011 22:31:01

Re: goto в С++.

Сообщение Errorkpi »

Помню в универе я долго холиварил с одним С (не С++) кодером, который любил goto, и не верил в работу программ без него.
Все применение этого оператора в его коде сводилось к прерыванию цикла (не доходя до конца счета, или переход на следующую итерацию), и выход из функции при различных условиях (где не применим глобальный IF, например по нажатию на кнопку на неопределенной итерации бесконечного цикла (BorlandC3.11) ).
Вот так мы и холиварили, я писал break, continue и return var, а он goto lable и все тут.
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: goto в С++.

Сообщение SergeBS »

Errorkpi писал(а):Вот так мы и холиварили, я писал break, continue и return var, а он goto lable и все тут.

Если пишешь ты на Си
Будь хоть трижды ламер
Про такого говорят:
"Он крутой програмер"
(с) Неизвестный пасквилянт ( ПАСКвилянт от pascal, и соответственно есть и наСИльники - от С) :)
Отмазка - мне по большому счету пофигу, что C/C++. что Pascal/Delphi. Переключаться конечно тяжко. Но возможно.
Человек - это звучит гордо, а обезьяна - объективно...
SfS
Друг Кота
Сообщения: 19288
Зарегистрирован: Пт янв 12, 2007 11:21:39
Откуда: Томск

Re: goto в С++.

Сообщение 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 встречается в моих программах не часто, но лишь оно уместно.

Может, всё, что я написал покажется многим очевидным, а может кому и пригодится.
Аватара пользователя
SergeBS
Вымогатель припоя
Сообщения: 683
Зарегистрирован: Пт апр 11, 2008 11:24:53
Откуда: Владимир

Re: goto в С++.

Сообщение 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) имеют право на существование. Какой лучше - зависит от задачи (и опыта программиста) . :beer:
ЗЫ: начинающим goto лучше избегать. Поскольку либо без него НУЖНО обойтись, либо задачка - не для начинающих. Остальное - крайне редко. :)
Человек - это звучит гордо, а обезьяна - объективно...
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: goto в С++.

Сообщение 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;
}
Последний раз редактировалось avreal Пт сен 23, 2011 11:05:40, всего редактировалось 1 раз.
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
avreal
Опытный кот
Сообщения: 842
Зарегистрирован: Чт дек 31, 2009 19:27:45
Откуда: Бровари, Україна
Контактная информация:

Re: goto в С++.

Сообщение 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 тоже не использую. Просто и так могу написать для демонстрации. И, как видите -- компилируется во вполне нормальный код :)))
Лень в виде мании величия: «ты гений, зачем стараться?». В виде комплекса: «всё равно не выйдет, зачем упираться?». Как логика: «если достаточно, зачем знать и уметь больше?». Цель одна: остановить. Не любит тепло работающих мышц и шум работающего мозга.
Аватара пользователя
Errorkpi
Встал на лапы
Сообщения: 102
Зарегистрирован: Вт мар 22, 2011 22:31:01

Re: goto в С++.

Сообщение Errorkpi »

avreal писал(а):#define BREAKABLE_BLOCK \

Мда....
Господин знает толк в извращениях..... :tea:
Закрыто

Вернуться в «Микроконтроллеры и ПЛИС»