GOTO, который все еще рассматривают вредным? [закрытый]

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

273
задан 16 revs, 10 users 71% 22 July 2016 в 09:28
поделиться

44 ответа

Следующие утверждения являются обобщениями; в то время как всегда возможно умолять исключение, это обычно (по моему опыту, и скромное мнение) не стоит рисков.

  1. Неограниченное использование адресов памяти (или GOTO или необработанные указатели) обеспечивает слишком много возможностей сделать легко преодолимые ошибки.
  2. , Чем больше путей там состоит в том, чтобы прибыть в конкретное "местоположение" в коде, тем менее уверенный может быть, о каком состояние системы в той точке. (См. ниже.)
  3. Структурное программирование, по моему скромному мнению, меньше о "предотвращении GOTOs" и больше о том, чтобы заставлять структуру кода соответствовать структуре данных. Например, повторяющаяся структура данных (например, массив, последовательный файл, и т.д.) естественно обрабатывается повторной единицей кода. Наличие встроенных структур (например, в то время как, поскольку, пока, для - каждый, и т.д.) не позволяет программисту избегать скуки повторения тех же шаблонных кодовых комбинаций.
  4. , Даже если GOTO является деталью реализации низкого уровня (не всегда случай!) это ниже уровня, что программист должен думать. Сколько программистов балансирует свои персональные чековые книжки в необработанном двоичном файле? Сколько программистов волнуется, о котором сектор на диске содержит конкретную запись, вместо того, чтобы просто обеспечить ключ к механизму базы данных (и сколько путей вещи могли пойти не так, как надо, если бы мы действительно записали все наши программы с точки зрения секторов физического диска)?

Сноски к вышеупомянутому:

Относительно точки 2, рассмотрите следующий код:

a = b + 1
/* do something with a */

В "делают что-то" указывает в коде, мы можем заявить с высокой уверенностью, что a больше, чем b. (Да, я игнорирую возможность незахваченного целочисленного переполнения. Давайте не срывать простой пример.)

, С другой стороны, если код считал этот путь:

...
goto 10
...
a = b + 1
10: /* do something with a */
...
goto 10
...

разнообразие способов добраться до маркировки 10 означает, что мы должны работать намного тяжелее, чтобы быть уверенными в отношениях между a и b в той точке. (На самом деле в общем случае это undecideable!)

Относительно точки 4, целое понятие "движения где-нибудь" в коде является просто метафорой. Ничто действительно не "идет" никуда в ЦП кроме электронов и фотонов (для сбросного тепла). Иногда мы бросаем метафору для другого, более полезного, один. Я вспоминаю обнаружение (несколько десятилетий назад!) язык, где

if (some condition) {
  action-1
} else {
  action-2
}

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

178
ответ дан 5 revs, 5 users 90% 23 November 2019 в 02:12
поделиться

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

3
ответ дан Brian R. Bondy 23 November 2019 в 02:12
поделиться

Я на самом деле нашел меня вынужденным использовать goto, потому что я буквально не мог думать о лучшем (более быстром) способе записать этот код:

у меня был сложный объект, и я должен был сделать некоторую операцию на нем. Если бы объект был в одном состоянии, то я мог сделать быструю версию операции, иначе я должен был сделать медленную версию операции. Вещь состояла в том, что в некоторых случаях, посреди медленной операции, было возможно понять, что это, возможно, было сделано с быстрой операцией.

SomeObject someObject;    

if (someObject.IsComplex())    // this test is trivial
{
    // begin slow calculations here
    if (result of calculations)
    {
        // just discovered that I could use the fast calculation !
        goto Fast_Calculations;
    }
    // do the rest of the slow calculations here
    return;
}

if (someObject.IsmediumComplex())    // this test is slightly less trivial
{
    Fast_Calculations:
    // Do fast calculations
    return;
}

// object is simple, no calculations needed.

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

Hugo

4
ответ дан Rocketmagnet 23 November 2019 в 02:12
поделиться

Я избегаю его, так как коллега/менеджер, несомненно, подвергнет сомнению его использование или в обзоре кода или когда они споткнутся через него. В то время как я думаю, что это имеет использование (случай обработки ошибок, например) - Вы столкнетесь с некоторым другим разработчиком, у которого будет некоторый тип проблемы с ним.

It’s, не стоящий того.

4
ответ дан 2 revs 23 November 2019 в 02:12
поделиться

Я могу только вспомнить использование goto однажды. У меня была серия пяти вложенных считаемых циклов, и я должен был быть в состоянии убежать из всей структуры с внутренней части рано на основе определенных условий:

for{
  for{
    for{
      for{
        for{
          if(stuff){
            GOTO ENDOFLOOPS;
          }
        }
      }
    }
  }
}

ENDOFLOOPS:

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

Никакой velociraptors не напал на меня.

119
ответ дан 3 revs, 2 users 93% 23 November 2019 в 02:12
поделиться

У нас уже был этот обсуждение , и я стою в стороне моя точка .

, Кроме того, я сыт по горло людьми, описывающими высокоуровневые структуры языка как “ goto в disguise”, потому что у них ясно нет точки во всем . Например:

Даже усовершенствованная управляющая структура продолжения в Схеме может быть описана как сложный goto.

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

Точно так же высказывание “GOTO является инструментом, и как всеми инструментами, это может использоваться, и abused” полностью от метки. Никакой современный рабочий-строитель не использовал бы скалу и требовал бы его “is инструмент. Скалы ” были заменены молотками. goto был заменен управляющими структурами. Если бы рабочий-строитель был скручен в дикой природе без молотка, конечно, он использовал бы скалу вместо этого. Если программист должен использовать нижний язык программирования, который не имеет функции X, ну, в общем, конечно, ей, вероятно, придется использовать goto вместо этого. Но если она использует его где-нибудь еще вместо соответствующей функции языка, она ясно не поняла язык правильно и использует его неправильно. Это действительно настолько просто.

91
ответ дан 3 revs 23 November 2019 в 02:12
поделиться

Goto является чрезвычайно низким в моем списке вещей включать в программу только ради него. Это не означает, что это недопустимо.

Goto может быть хорошим для конечных автоматов. Оператор переключения в цикле (в порядке типичной важности): (a) не на самом деле представительный для потока управления, (b) ужасный, (c) потенциально неэффективный в зависимости от языка и компилятора. Таким образом, Вы заканчиваете тем, что писали одну функцию на состояние и сделали вещи как "возврат NEXT_STATE"; которые даже похожи на goto.

Предоставленный, трудно кодировать конечные автоматы способом, которые делают их легкими понять. Однако ничего подобного, трудность относится к использованию goto и ни одному из него, не может быть уменьшен при помощи альтернативных управляющих структур. Если Ваш язык не имеет конструкцию 'конечного автомата'. Мой не делает.

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

setjmp/longjmp может быть хорошим для реализации исключений или подобного исключению поведения. В то время как не универсально похваливший, исключения обычно считают "допустимой" управляющей структурой.

setjmp/longjmp 'более опасны', чем goto в том смысле, что их более трудно использовать правильно, не берите в голову понятно.

никогда не было, и при этом никогда не будет, никакой язык, на котором это - наименее разрядное трудное для записи плохого кода. - Donald Knuth.

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

Следующий это будут "указатели, которые рассматривают вредными", тогда "утиный ввод, который рассматривают вредным". Тогда, кого оставят защитить Вас, когда они прибудут для убирания небезопасной конструкции программирования? А?

90
ответ дан 2 revs 23 November 2019 в 02:12
поделиться

В Linux: Используя goto В Коде Ядра на Прерывании Ядра, существует обсуждение с Linus Torvalds и "новым парнем" об использовании GOTOs в коде Linux. Существуют некоторые очень положительные стороны там и Linus, одетый в то обычное высокомерие:)

Некоторые проходы:

Linus: "нет, Вам промыли мозги люди CS, которые думали, что Niklaus Wirth на самом деле знал то, о чем он говорил. Он не сделал. У него нет трахающей подсказки".

-

Linus: "Я думаю, что goto's прекрасен, и они часто более читаемы, чем большие объемы добавления отступа".

-

Linus: "Конечно, на глупых языках как Паскаль, где маркировки не могут быть описательными, goto's может быть плохим".

67
ответ дан 4 revs, 3 users 85% 23 November 2019 в 02:12
поделиться

В C, goto только работы в рамках текущей функции, которая имеет тенденцию локализовать любые потенциальные ошибки. setjmp и longjmp намного более опасны, будучи нелокальным, сложным и зависящим от реализации. На практике однако они являются слишком неясными и редкими для порождения многих проблем.

я полагаю, что опасность goto в C значительно преувеличена. Помните, что исходные goto аргументы произошли назад в эпоху языков как ОСНОВНОЙ старомодный, где новички запишут запутанный код как это:

3420 IF A > 2 THEN GOTO 1430

Здесь Linus описывает соответствующее использование goto: http://www.kernel.org/doc/Documentation/CodingStyle (глава 7).

50
ответ дан 2 revs 23 November 2019 в 02:12
поделиться

Donald E. Knuth ответил на этот вопрос в книге "Грамотное программирование", 1992 CSLI. На p. 17 существует эссе" Структурное программирование с операторами перехода " (PDF). Я думаю, что статья, возможно, была опубликована в других книгах также.

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

статья содержит полное описание проблемы, историю, примеры и встречные примеры.

30
ответ дан 2 revs, 2 users 83% 23 November 2019 в 02:12
поделиться

Притянутый Jay Ballou, добавляющим ответ, добавлю я свой ВЈ0.02. Если бы Bruno Ranschaert уже не сделал так, то я упомянул бы статью "Structured Programming with GOTO Statements" Knuth.

Одной вещью, которую я не видел обсужденный, является вид кода, который, в то время как не точно распространенный, преподавался в учебниках Фортрана. Вещи как расширенный диапазон цикла типа DO и открыто кодированных подпрограмм (помнят, это был бы Фортран II или Фортран IV или Фортран 66 - не Фортран 77 или 90). Существует, по крайней мере, шанс, что синтаксические детали неточны, но понятия должны быть достаточно точными. Отрывки в каждом случае в единственной функции.

Примечание, которое превосходные, но датированное (и распроданный) заказывают' Элементы Стиля программирования, 2-й Edn' Kernighan & Plauger включает некоторые реальные примеры злоупотребления GOTO от программирования учебников его эры (последние 70-е). Материал ниже не из той книги, как бы то ни было.

Расширенный диапазон для цикла типа DO

       do 10 i = 1,30
           ...blah...
           ...blah...
           if (k.gt.4) goto 37
91         ...blah...
           ...blah...
10     continue
       ...blah...
       return
37     ...some computation...
       goto 91

Одной причиной такой ерунды была хорошая старомодная перфокарта. Вы могли бы заметить, что маркировки (приятно из последовательности, потому что это было каноническим стилем!) находятся в столбце 1 (на самом деле, они должны были быть в столбцах 1-5), и код находится в столбцах 7-72 (столбец 6 был столбцом маркера продолжения). Столбцам 73-80 дали бы порядковый номер, и были машины, которые отсортируют деки перфокарты в порядок порядкового номера. Если бы Вы имели свою программу на упорядоченных картах и должны были добавить несколько карт (строки) в середину цикла, то необходимо будет повторно перфорировать все после тех дополнительных строк. Однако при замене одной карты материалом GOTO Вы могли бы постараться не повторно упорядочивать все карты - Вы просто подвернули новые карты в конце стандартной программы с новыми порядковыми номерами. Полагайте, что это первая попытка '"зеленых" вычислений' - сохранения перфокарт (или, более конкретно, сохранения перепечатывания труда - и сохранения последовательных ошибок повторного ввода).

, О, Вы могли бы также отметить, что я обманываю и не кричу - Фортран, который IV обычно писался во всем верхнем регистре.

Открыто кодированная подпрограмма

       ...blah...
       i = 1
       goto 76
123    ...blah...
       ...blah...
       i = 2
       goto 76
79     ...blah...
       ...blah...
       goto 54
       ...blah...
12     continue
       return
76     ...calculate something...
       ...blah...
       goto (123, 79) i
54     ...more calculation...
       goto 12

GOTO между маркирует 76, и 54 версия вычисленного goto. Если переменная у меня есть значение 1, goto первая маркировка в списке (123); если это имеет значение 2, goto второе, и так далее. Фрагмент от 76 до вычисленного goto является открыто кодированной подпрограммой. Это была часть кода, выполненного скорее как подпрограмма, но выписанного в теле функции. (Фортран также имел функции оператора - которые были встроены функции, которые соответствовали на одной строке.)

были худшие конструкции, чем вычисленный goto - Вы могли присвоить маркировки переменным и затем использовать присвоенный goto. При поиске с помощью Google присвоенный goto говорит мне, что был удален из Фортрана 95. Запишите на свой счет один для оборота структурного программирования, который, как могли справедливо говорить, запустил на публике с "GOTO Dijkstra Продуманную Вредную" букву или статью.

Без некоторого ведома видов вещей, которые были сделаны в Фортране (и на других языках, большинство которых справедливо оказалось нереально), нам вновь прибывшие трудно понять объем проблемы, с которой имел дело Dijkstra. Heck, я не начинал программировать до десяти лет после того, как та буква была опубликована (но у меня действительно была неудача к программе в Фортране IV некоторое время).

24
ответ дан 3 revs 23 November 2019 в 02:12
поделиться

Если бы сами GOTO были злыми, компиляторы были бы злыми, потому что они генерируют JMPs. Если вскакивание в блок кода, особенно после указателя, было по сути злым, инструкция по Возврату будет злой. Скорее зло находится в потенциале для злоупотребления.

Время от времени я должен был записать приложения, которые должны были отслеживать много объектов, где каждый объект должен был следовать за сложной последовательностью состояний в ответ на события, но все это было определенно единственным потоком. Типичная последовательность состояний, если представлено в псевдокоде была бы:

request something
wait for it to be done
while some condition
    request something
    wait for it
    if one response
        while another condition
            request something
            wait for it
            do something
        endwhile
        request one more thing
        wait for it
    else if some other response
        ... some other similar sequence ...
    ... etc, etc.
endwhile

я уверен, что это не является новым, но способ, которым я обработал его в C (++), состоял в том, чтобы определить некоторые макросы:

#define WAIT(n) do{state=(n); enque(this); return; L##n:;}while(0)
#define DONE state = -1

#define DISPATCH0 if state < 0) return;
#define DISPATCH1 if(state==1) goto L1; DISPATCH0
#define DISPATCH2 if(state==2) goto L2; DISPATCH1
#define DISPATCH3 if(state==3) goto L3; DISPATCH2
#define DISPATCH4 if(state==4) goto L4; DISPATCH3
... as needed ...

Тогда (принимающий состояние первоначально 0) структурированный конечный автомат выше превращается в структурированный код:

{
    DISPATCH4; // or as high a number as needed
    request something;
    WAIT(1); // each WAIT has a different number
    while (some condition){
        request something;
        WAIT(2);
        if (one response){
            while (another condition){
                request something;
                WAIT(3);
                do something;
            }
            request one more thing;
            WAIT(4);
        }
        else if (some other response){
            ... some other similar sequence ...
        }
        ... etc, etc.
    }
    DONE;
}

С изменением на этом, может быть ВЫЗОВ и ВОЗВРАТ, таким образом, некоторые конечные автоматы могут действовать как подпрограммы других конечных автоматов.

действительно ли это необычно? Да. Требуется некоторое изучение со стороны специалиста по обслуживанию? Да. Это учение наизусть платит? Я думаю так. Это могло обойтись без GOTOs, которые вскакивают в блоки? Нет.

5
ответ дан 2 revs 23 November 2019 в 02:12
поделиться

Нет таких вещей как GOTO, которую рассматривают вредной .

GOTO является инструментом, и как всеми инструментами, он может использоваться, и злоупотребил .

существуют, однако, много инструментов в мире программирования, которые имеют тенденцию быть , злоупотребили [еще 112], чем быть использовало , и GOTO является одним из них. оператор WITH Дельфи - другой.

Лично я не использую ни один в типичном коде , но у меня было нечетное использование и GOTO и С , которые были гарантированы, и альтернативное решение будет содержать больше кода.

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

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

21
ответ дан 2 revs, 2 users 95% 23 November 2019 в 02:12
поделиться

Если Вы пишете VM в C, оказывается что использование вычисленного gotos (gcc) как это:

char run(char *pc) {
    void *opcodes[3] = {&&op_inc, &&op_lda_direct, &&op_hlt};
    #define NEXT_INSTR(stride) goto *(opcodes[*(pc += stride)])
    NEXT_INSTR(0);
    op_inc:
    ++acc;
    NEXT_INSTR(1);
    op_lda_direct:
    acc = ram[++pc];
    NEXT_INSTR(1);
    op_hlt:
    return acc;
}

работы намного быстрее, чем стандартный переключатель в цикле.

15
ответ дан vt. 23 November 2019 в 02:12
поделиться

Отклонение использования Оператора перехода программистам похоже на сообщение плотнику не использовать молоток, поскольку это Могло бы повредить стену, в то время как он вбивает гвоздь. Настоящий программист Знает, Как и Когда использовать GOTO. I’ve следовал позади некоторых из них, так называемый ‘Structured Programs’ I’ve видит такой Неприятный код только для избегания использования GOTO, что я мог стрелять в программиста. Хорошо, В защиту другой стороны, I’ve, замеченный некоторый реальный запутанный код также и снова, те программисты должны быть застрелены также.

Вот является всего один небольшой пример кода найденным I’ve.

  YORN = ''
  LOOP
  UNTIL YORN = 'Y' OR YORN = 'N' DO
     CRT 'Is this correct? (Y/N) : ':
     INPUT YORN
  REPEAT
  IF YORN = 'N' THEN
     CRT 'Aborted!'
     STOP
  END

-----------------------ИЛИ----------------------

10:  CRT 'Is this Correct (Y)es/(N)o ':

     INPUT YORN

     IF YORN='N' THEN
        CRT 'Aborted!'
        STOP
     ENDIF
     IF YORN<>'Y' THEN GOTO 10
10
ответ дан 2 revs, 2 users 86% 23 November 2019 в 02:12
поделиться

"В этой ссылке http://kerneltrap.org/node/553/2131 "

Как ни странно, устраняя goto представил ошибку: вызов спин-блокировки был опущен.

8
ответ дан Jay Ballou 23 November 2019 в 02:12
поделиться

Исходная бумага должна считаться "Безусловной GOTO, Продуманной Вредный". Это в особенности защищало форму программирования на основе условного выражения (if) и повторяющееся (while) конструкции, а не тест-и-переход, распространенный, чтобы рано кодировать. goto все еще полезно на некоторых языках или обстоятельствах, где никакая соответствующая управляющая структура не существует.

7
ответ дан John Millikin 23 November 2019 в 02:12
поделиться

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

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

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

всегда возможно сделать его правильно без goto, но в этом случае и немногие другие Goto является на самом деле лучшим решением, прежде всего, для удобочитаемости и пригодности для обслуживания.

-Adam

6
ответ дан Adam Davis 23 November 2019 в 02:12
поделиться

Одно современное использование GOTO компилятором C# для создания конечных автоматов для перечислителей, определенных возвратом урожая.

GOTO - что-то, что должно использоваться компиляторами и не программистами.

5
ответ дан Brian Leahy 23 November 2019 в 02:12
поделиться

Пока C и C++ (среди других преступников) не маркировали повреждения, и продолжается, goto продолжит иметь роль.

5
ответ дан DrPizza 23 November 2019 в 02:12
поделиться

Иногда это допустимо для использования GOTO в качестве альтернативы обработке исключений в единственной функции:

if (f() == false) goto err_cleanup;
if (g() == false) goto err_cleanup;
if (h() == false) goto err_cleanup;

return;

err_cleanup:
...

код COM, кажется, следует этой модели справедливо часто.

129
ответ дан Rob Walker 23 November 2019 в 02:12
поделиться

XKCD's GOTO Comic

мой коллега А сказал, что единственная причина использовать GOTO состоит в том при программировании себя до сих пор в угол, что это - единственный выход. Другими словами, надлежащий дизайн загодя и Вы не должны будете использовать GOTO позже.

я думал, что этот комик иллюстрирует, что красиво "Я мог реструктурировать поток программы или использовать тот мало 'GOTO' вместо этого". GOTO является слабым выходом, когда у Вас есть слабый дизайн. Velociraptors охотятся на слабое .

240
ответ дан 10 revs, 4 users 83% 23 November 2019 в 02:12
поделиться

Go To может обеспечить своего рода замену для «реальной» обработки исключений в определенных случаях. Подумайте:

ptr = malloc(size);
if (!ptr) goto label_fail;
bytes_in = read(f_in,ptr,size);
if (bytes_in=<0) goto label_fail;
bytes_out = write(f_out,ptr,bytes_in);
if (bytes_out != bytes_in) goto label_fail;

Очевидно, этот код был упрощен, чтобы занимать меньше места, поэтому не зацикливайтесь на деталях. Но рассмотрим альтернативу, которую я видел слишком много раз в коде production , так как кодеры идут на абсурдные длины, чтобы избежать использования goto:

success=false;
do {
    ptr = malloc(size);
    if (!ptr) break;
    bytes_in = read(f_in,ptr,size);
    if (count=<0) break;
    bytes_out = write(f_out,ptr,bytes_in);
    if (bytes_out != bytes_in) break;
    success = true;
} while (false);

Теперь функционально этот код делает то же самое. На самом деле код, сгенерированный компилятором, практически идентичен. Однако в стремлении программиста к умиротворению Ногото (страшного бога академического упрека) этот программист полностью нарушил основную идиому, которую представляет цикл , в то время как , и сделал действительное число на удобочитаемость кода. Это не лучше.

Итак,

34
ответ дан tylerl 23 November 2019 в 02:12
поделиться

Такого никогда не было, пока вы могли думать сами.

16
ответ дан stesch 23 November 2019 в 02:12
поделиться

Так как я начал делать некоторые вещи в ядре Linux, gotos не беспокоит меня так сильно, как раньше. Сначала я был в ужасе от того, что они (ребята из ядра) добавили gotos в мой код. С тех пор я привык к использованию gotos, в некоторых ограниченных контекстах, и теперь буду иногда использовать их сам. Как правило, это переход, который переходит к концу функции, чтобы выполнить какую-то очистку и выручить, а не дублировать ту же самую очистку и выкуп в нескольких местах в функции. И, как правило, это не что-то достаточно большое для передачи другой функции - например, освобождение некоторых локально (k) malloc-переменных является типичным случаем.

I ' Я написал код, который использовал setjmp / longjmp только один раз. Это было в программе MIDI-барабанного секвенсора. Воспроизведение происходило в отдельном процессе от всего взаимодействия с пользователем, и процесс воспроизведения использовал общую память с процессом пользовательского интерфейса, чтобы получить ограниченную информацию, необходимую для воспроизведения. Когда пользователь хотел остановить воспроизведение, процесс воспроизведения просто выполнял longjmp «назад в начало», чтобы начать сначала, а не какое-то сложное раскручивание того места, где оно выполнялось, когда пользователь хотел остановить его. Он отлично работал, был прост, и у меня никогда не было проблем или ошибок, связанных с этим в этом случае.

У setjmp / longjmp есть свое место - но это место, которое вы вряд ли посетите, но один раз за очень долгое время. в то время как.

Редактировать: я только что посмотрел на код. На самом деле я использовал siglongjmp (), а не longjmp (не то, чтобы это было важно,

17
ответ дан 23 November 2019 в 02:12
поделиться

Чтобы исправить это, см. это сообщение в блоге Аарона Стебнера:

  • Ваше приложение, вероятно, определяется PCA (помощником по совместимости программ) как не-Vista (до Vista) установочное приложение.
  • Вам нужно будет добавить встроенный манифест и установить требуемый уровень выполнения

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

есть прозаическая и злая сторона для goto .

Прозаическая сторона заключается в том, что направленный вверх goto может реализовать Совершенно разумный цикл и переход, направленный вниз, могут сделать вполне разумный break или return . Конечно, фактическое while , break или return было бы намного более читаемым, поскольку бедному человеку не пришлось бы моделировать эффект goto , чтобы получить полную картину. Итак, в целом плохая идея.

Злая сторона включает подпрограмму, не использующую goto для while, break или return, а использующую ее для так называемой логики спагетти . В этом случае разработчик, довольный goto, строит фрагменты кода из лабиринта goto, и единственный способ понять это - мысленно смоделировать его в целом, что ужасно утомительно при большом количестве goto. Я имею в виду, представьте себе проблему оценки кода, где else не является в точности обратным if , где вложенные if могут допускать некоторые вещи, которые были отклонено внешним if и т. д. и т. д.

Наконец, чтобы действительно охватить эту тему, мы должны отметить, что практически все ранние языки, кроме Algol, изначально делали только отдельные утверждения, подчиняющиеся их версиям если-то-еще . Таким образом, единственный способ создать условный блок - это перейти к вокруг него, используя обратное условное выражение. Безумие, я знаю, но я читал некоторые старые спецификации. Помните, что первые компьютеры были запрограммированы в двоичном машинном коде, поэтому я полагаю, что любой вид HLL был спасением; Я полагаю, они не были слишком разборчивы в том, какие именно возможности HLL у них есть.

Сказав все, что я использовал, вставлял один goto в каждую программу, которую я написал , «просто чтобы раздражать пуристов» .

13
ответ дан 23 November 2019 в 02:12
поделиться

Сегодня трудно понять, что такого в операторе GOTO, потому что люди "структурированного программирования" в основном выиграли дебаты, и современные языки имеют достаточно структур потока управления, чтобы избежать GOTO.

Подсчитайте количество goto в современной программе на языке Си. Теперь добавьте количество операторов break, continue и return. Кроме того, добавьте количество раз, когда вы используете if, else, while, switch или case. Примерно столько GOTOбыло бы в вашей программе, если бы вы писали на FORTRAN или BASIC в 1968 году, когда Дейкстра написал свое письмо.

Языкам программирования того времени не хватало потока управления. Например, в оригинальном дартмутском BASIC:

  • IF операторы не имели ELSE. Если вам нужен был один, вы должны были написать:

    100 IF NOT condition THEN GOTO 200
    ...что делать, если условие истинно...
    190 GOTO 300
    200 REM else
    ...что делать, если условие ложно...
    300 REM end if
    
  • Даже если ваш оператор IF не нуждался в ELSE, он все равно был ограничен одной строкой, которая обычно состояла из GOTO.

  • Не было DO...LOOP. Для циклов, не являющихся FOR, вы должны были завершить цикл явным GOTO или IF...GOTO, вернувшись к началу.

  • Не было SELECT CASE. Приходилось использовать ON...GOTO.

Таким образом, в итоге вы получали много GOTO в своей программе. И вы не могли полагаться на ограничение GOTO в пределах одной подпрограммы (потому что GOSUB...RETURN был таким слабым понятием подпрограмм), так что эти GOTOмогли идти куда угодно. Очевидно, что это затрудняло следование потока управления.

Отсюда возникло движение против GOTO.

47
ответ дан 23 November 2019 в 02:12
поделиться

Практически во всех ситуациях, когда можно использовать goto, вы можете сделать то же самое, используя другие конструкции. В любом случае Goto используется компилятором.

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

4
ответ дан 23 November 2019 в 02:12
поделиться

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

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

существуют некоторые ситуации, где это - единственный путь к потоку управления, но тех ситуаций можно избежать.

3
ответ дан 2 revs, 2 users 89% 23 November 2019 в 02:12
поделиться

На каждой платформе я видел, управляющие структуры высокого уровня реализованы как низкий уровень gotos (переходы). Например, виртуальная машина Java имеет код байта Перехода, но ничто, для если, еще, в то время как, поскольку, и т.д.

И некоторые из этих компиляторов создают запутанный код для простого условного блока.

Для ответа на вопрос goto все еще считают вредным люди, которые полагают, что он вреден. Goto облегчает терять преимущества структурного программирования.

В конце, это - Ваша программа; и поэтому Ваше решение. Я предлагаю не использовать goto, пока Вы не в состоянии ответить на свой вопрос сами, но в контексте определенной проблемы.

2
ответ дан eet_1024 23 November 2019 в 02:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: