2013-07-19 2 views
3

Я написал некоторые программы PL/SQL, где я нашел GOTO полезным, например, прыгать из вложенных циклов и т. Д.Почему компилятор не может (всегда?) Оптимизировать код с GOTO?

Мне было интересно, если это действительно плохая идея использовать gotos на других языках. (. Например C++)

Я нашел эти вопросы:

GOTO still considered harmful?

effect of goto on C++ compiler optimization

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

И в другом: «Возможно, однако, чтобы получить график потока с GOTOS, которые не могут быть получены с помощью любых обычных операторов управления потоком (петли, переключатель и т.п.)»

I мне сказали, что это зло, но никто не сказал мне, почему, за исключением кодов с gotos, ужасно читать. Ну, если никто не узнает, понимает, как их использовать, потому что они «злые», их никто не может читать.

В каких случаях компилятор МОЖЕТ и НЕ МОЖЕТЕ оптимизировать код, содержащий GOTO? Зачем?

ответ

2

Большой толстый отказ от ответственности:

Я задавался вопросом, если это действительно плохая идея использовать в других последовательно открывает языках. (Например, C++.)

За исключением одного исключения (C, упомянутого ниже), которое сочетается с большой дисциплиной, это почти никогда не является хорошей идеей. Это зависит от языка, поэтому спросите своего местного гуру, но вероятность того, что вы найдете хороший вариант использования, довольно тонкая. Err на стороне осторожности. Скорее всего, язык имеет более идиоматический и более четкий способ делать то, что вы склонны использовать goto.


Это не столько случай «не может когда-либо» или прерывающимся-проблемы-невозможно, как «просто нецелесообразно». Иногда, особенно если вы просто спрячете свои петли, вручную набрав эквивалент goto s (что за глупость!), Это может сработать случайно. В других случаях, особенно если график потока управления напоминает спагетти или в противном случае является странным/необычным, компилятор не может ничего оптимизировать.

Есть только так много времени и мысли, чтобы вставить в оптимизационные проходы, и только столько времени, сколько компилятор может потратить на выполнение оптимизационных проходов. Гораздо выгоднее сосредоточиться на широко используемых, хорошо понятных моделях потока управления, встроенных в большинство языков (петля , петли с расчетом на запуск, ранние return, switch, цепочки else if и т. Д.). Даже когда оптимизация происходит на IR, который поддерживает толькоgoto -образный поток управления, эти шаблоны приводят к предсказуемым, легко распознанным маскировкам, и оптимизация настраивается для их поиска. Это то, о чем говорит второе предложение, о котором вы приводите. Если код перескакивает назад и вперед способом, совершенно непохожим на цикл, проход для разворота цикла не даст ему времени суток, даже если это на самом деле умный (плохой вид умного) способ записи »сделать это четыре раза ».

До сих пор я предполагал, что goto, как и у стандартного C —, то есть целевая метка известна статически и ограничена чести других языковых конструкций (например, только прыгать внутри одной функции). Существуют расширения, которые позволяют прыгать на произвольные, динамически выбранные цели (например, «вычисленный goto»). Их гораздо сложнее проанализировать (и, следовательно, оптимизировать), вероятно, в том же самом шаге, что и указатели на функции.

Мне сказали, что это зло, но никто не сказал мне, почему, за исключением кодексов с gotos, ужасно читать. Ну, если никто не узнает, понимает, как их использовать, потому что они «злые», их никто не может читать.

Тогда те, кто вам сказал, сделали плохую работу. Это не вопрос к этому, поэтому я буду держать его в курсе: 99% управляющего потока вписываются в очень немногие категории, которые требуют специализированных конструкций управления потоком. Использование единой конструкции GOTO для всех этих случаев скрывает намерение, это больше кода, и для понимания того, что делает код, требуется больше времени. Вы можете испытать это из первых рук: Напишите несколько разумно сложных> 100 строк командных файлов (этот ужасный древний язык сценариев Windows).

Ах, еще одна вещь:

Я нашел GOTO полезным, как выпрыгивает из вложенных циклов

Это потенциально нормально использовать, но большинство языков обеспечивают более четкие способы сделать это. В качестве альтернативы, сгладьте петлю (например, с Python itertools.combinations) и break, или поместите вложенный цикл в отдельную функцию (во всяком случае, хорошая идея) и return.

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

+0

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

+1

@IraBaxter Ну, '(1) переключатель (состояние)' не так уж плохо. Я прекрасно знаю, какой код может генерировать и какая дополнительная работа влечет за собой, но я не могу заставить себя заботиться, и я сомневаюсь, что это важно для большинства программ (сколько это, пятьдесят циклов за переход?). Если мне нужен такой уровень производительности, я думаю, что могу пойти на лишнюю милю и создать eDSL, который позаботится об этих вещах (или использовать существующий, если это применимо), или написать все в сборке. – delnan

+0

Переключатель (состояние) вызывает разрыв трубопровода в каждом цикле. Если вам все равно, тогда вам все равно, иначе вы это сделаете, а прямой goto лучше. Стыдно, что нужно выйти за пределы языка, чтобы сделать простой переход. Я согласен, большинству программ это не нужно, но его достаточно легко написать структурированный код, где он не нужен. Но тогда большинство из них не нужно писать ни на одном компилированном языке. –

Смежные вопросы