Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

goto vs ...

21K
02 января 2007 года
kerdan
18 / / 27.12.2006
Цитата: nilbog
можно фунцию ввести которая проверяет просто число или нет
 
Код:
function prost(num:integer):boolean;
label 1;
var i:integer;
begin
prost:=true;
for i:=2 to num div 2 do
 if num mod i = 0 then begin prost:=false; goto 1 end;
1:
end;



Не понял? А какая необходимость goto в if втыкать.
Во-первых там можно break поставить (выход из цикла).
Во-вторых там вообще надо уже exit'ом из ф-и выходить.

P.S. Это так - к слову.

Страницы:
4.6K
18 июля 2007 года
SerG1nho
72 / / 30.10.2006
Если мне не изменяет память, то нам препод на паре сказал, что label'ы каким то образом влияют на адресса памяти при выполнении программы, что может привести к глюкозаврам. Так это?
9.6K
19 июля 2007 года
quakersasha
23 / / 21.10.2005
Цитата: SerG1nho
Если мне не изменяет память, то нам препод на паре сказал, что label'ы каким то образом влияют на адресса памяти при выполнении программы, что может привести к глюкозаврам. Так это?



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

7.8K
19 июля 2007 года
Tingo
201 / / 17.05.2007
Цитата: quakersasha
Не, скорее всего, в этом нет ничего плохого... но мне лично самому всё это не нравится))) Мне не понятно идея гоуту, если в любой ситуации (с которой я встречался) можно обойтись циклами.




А я вот встречался. Я не сторонник Goto.
Но я за его разумное использование!
Например какую-то прогу(игру). В конце спрашиваеш - начать сначала(Yes/No)? Если Yes то перебрасываеш в начало.
Вот в таких местах и разумно ставить goto.
Но не надо им злоупотреблять!
Лучше использовать Repeat/While чем везде понатыкивать goto.

У КАЖДОГО ИЗ НИХ ЕСТЬ СВОЕ МЕСТО!

29K
19 июля 2007 года
NanoBits
18 / / 18.07.2007
Цитата:

Ха... где-то кто-то считает что goto суть плохо.....
Если бы это было так, то такого оператора просто не существовало бы....
GOTO нужен....
и зачастую позволяет СОКРАТИТЬ и повысить УДОБОЧИТАЕМОСТЬ кода в разы....
Единственный момент -- не прыгать !!В!! функции и циклы, а из них пожалуйста...


ты прав, goto это jmp в асме
и поэтому goto не bad и не good

241
23 июля 2007 года
Sanila_san
1.6K / / 07.06.2005
Цитата: NanoBits
ты прав, goto это jmp в асме
и поэтому goto не bad и не good

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

Кроме прочего, в некоторых современных языках слово goto зарезервировано, но ничего не делает. Поэтому писать с goto - плохая привычка.

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

314
24 июля 2007 года
fanto
374 / / 15.02.2003
Цитата: Sanila_san
В обычных ПО- и ОО-языках использование goto считается плохим тоном, поскольку там всегда можно обойтись циклами, if-ами и т.п. Если кажется, что нельзя - достаточно хорошо подумать, и получится!


Так тоже нельзя..... Если надо выкопать большую яму можно использовать экскаватор, а можно "достаточно хорошо ПОРАБОТАТЬ, и получится!"... выкопать эту яму лопатой....
Дествительно ВОЗМОЖНО не использовать безусловный переход....
Но ведь возможно и не пользоваться for или while... почему-то пользуются...
Я просто хочу сказать, что бывают случаи, когда goto ОЧЕНЬ УПРОЩАЕТ чтение кода....
Ну там вложенный в n-нном колене цикл из которого надо выйти.... или еще что-то....
так что говорить о вредности, неструктурированности и т.д просто неправильно...
хороша только та программа которая работает!

5.7K
29 июля 2007 года
Vedrus
49 / / 29.10.2006
Цитата:

Ха... где-то кто-то считает что goto суть плохо.....
Если бы это было так, то такого оператора просто не существовало бы....
GOTO нужен....
и зачастую позволяет СОКРАТИТЬ и повысить УДОБОЧИТАЕМОСТЬ кода в разы....
Единственный момент -- не прыгать !!В!! функции и циклы, а из них пожалуйста...

И еще один аргумент в пользу goto:
А как вы думаете реализованы while и тому подобные циклы?


Согласен с fanto в одном. Есть случаи, когда наиболее предпочтителен goto. Всё остальное, извините, полный бред.

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

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

3
29 июля 2007 года
Green
4.8K / / 20.01.2000
Цитата: Vedrus

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


Автоматы можно и нужно делать без goto. Но об этом ещё можно спорить.
А по поводу скорости - полный бред!

242
29 июля 2007 года
Оlga
2.2K / / 04.02.2006
[COLOR=Red]Большая просьба ко ВСЕМ, высказывая свое мнение подкрепляйте их фактами и поменьше эмоций, иначе закрою топик. Все разборки через личные сообщения. Сообщения личного характера удалила. Не переходите на личности.

[/COLOR]
5.7K
29 июля 2007 года
Vedrus
49 / / 29.10.2006
Green, я до не давнего времени рассуждал также как и ты. Самому мне задачи решить не приходилось, где операция goto предпочтительна, но у меня убедили в их существовании.

Я в высшей математике не очень силён по этому конкретные формулы привести не могу, но суть такая.

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

При реализации структурными методами программирования это неизбежно приводит к тому, что рано или поздно мы оказываемся в глубине порядка 15 if’ов, из которых нужно выйти и завершить выполнение функции. Простейший if на asm’е представляет собой пару cmp/jz (это в среднем 140 тиков процессора), но простейшим он бывает редко. Помножим это число на 15. Против этого выступает jmp, который тоже в среднем выполняется за 140 тиков, но один раз! Да ещё вспомним, что эта функция используется для статистических расчётов и лежит внутри пяти-мерного цикла, и должна вычисляться в real-time. Что получается? Думаю дальше можно не считать.

Кстати сказать, Cишная функция return выполняется дольше джампа. Что выбирать – решать вам.

С автоматами та же проблема бывает. Ты (или я) с ней столкнёшься, если придётся свой компилятор делать.
242
29 июля 2007 года
Оlga
2.2K / / 04.02.2006
[quote=Verdus]Goto оправдан при программировании автоматной структуры и сложных математико-физических моделей, в которых важна скорость исполнения. Структуре программы это не вредит, но скорость существенно увеличивается.[/quote]
Быстрее чем использовать if, break? или построенные циклы при помощи goto быстрее for, while ...? В топике обсуждался уже один реальный пример когда if+goto быстрее чем if+break - выход из вложенных циклов, при помощи goto достаточно сделать один jump, тогда как при использование if'ов требуется несколько(чтобы разбить каждый цикл по отдельности, а при помощи гото можно сразу из всех выйти). А так, что goto, if, for, break etc. - одинаково реализованы при помощи переходов. или я ошибаюсь?

Цитата:
Cишная функция return выполняется дольше джампа.

Ты имеешь ввиду, что лучше не выходить из подпрограмм при помощи ретерн, который не возвращает значения? а использовать гото? Например:

 
Код:
int func(int x)
{
  if(x > 0) return 1;
  return 0;
}
как я могу в такой функции заменить ретерн на гото?
3
29 июля 2007 года
Green
4.8K / / 20.01.2000
Цитата: Vedrus
Green, я до не давнего времени рассуждал также как и ты. Самому мне задачи решить не приходилось, где операция goto предпочтительна, но у меня убедили в их существовании.


Конкретный пример, иначе, это пустая болтовня.

Цитата: Vedrus

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

При реализации структурными методами программирования это неизбежно приводит к тому, что рано или поздно мы оказываемся в глубине порядка 15 if’ов, из которых нужно выйти и завершить выполнение функции.


Не поверишь, это реализунтся (если с головой) совершенно иначе.

Цитата: Vedrus

Простейший if на asm’е представляет собой пару cmp/jz (это в среднем 140 тиков процессора), но простейшим он бывает редко. Помножим это число на 15. Против этого выступает jmp, который тоже в среднем выполняется за 140 тиков, но один раз! Да ещё вспомним, что эта функция используется для статистических расчётов и лежит внутри пяти-мерного цикла, и должна вычисляться в real-time. Что получается? Думаю дальше можно не считать.


А при чем тут вообще jmp?
Мы говорили про goto.
goto не тождество jmp

Цитата: Vedrus

Кстати сказать, Cишная функция return выполняется дольше джампа. Что выбирать – решать вам.


А сколько выполняется "Cишная функция return" ? :D
И при чем тут "джамп"?
М-да...

5.7K
29 июля 2007 года
Vedrus
49 / / 29.10.2006
Цитата:
как я могу в такой функции заменить ретерн на гото?


Да, тут у меня прокол. Только что дизассемблировал сишный вариант, получилось mov/jmp, всё путём.

Цитата:
Быстрее чем использовать if, break?


Да, быстрее. break выходит только из одного уровня {}. Т.е., если будет 15 циклов, то будет 15 брейков.

Цитата:
goto не тождество jmp


А компилятор си думает по другому:

Код:
//void main()
//{
00401090    push    ebp
00401091    mov ebp,esp
00401093    sub esp,40h
00401096    push    ebx
00401097    push    esi
00401098    push    edi
00401099    lea edi,[ebp-40h]
0040109C    mov ecx,10h
004010A1    mov eax,0CCCCCCCCh
004010A6    rep stos    dword ptr [edi]
//goto l1;
004010A8    jmp         l1+2 (004010ac)
//f();
//f();
//f();
//l1: ;
//}


Цитата:
Не поверишь, это реализунтся (если с головой) совершенно иначе.


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

242
29 июля 2007 года
Оlga
2.2K / / 04.02.2006
Цитата:
break выходит только из одного уровня {}. Т.е., если будет 15 циклов, то будет 15 брейков.

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

http://forum.codenet.ru/showpost.php?p=164484&postcount=13

5.7K
29 июля 2007 года
Vedrus
49 / / 29.10.2006
Ну да, из циклов и условий. Об этом и спорим. А ещё о том, что это не признак "кривого" кода. А другой темы я не видил, когда тут отвечал. Извините.
242
29 июля 2007 года
Оlga
2.2K / / 04.02.2006
Цитата:
А ещё о том, что это не признак "кривого" кода.


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

Цитата:
другой темы я не видил, когда тут отвечал


да ты и не должен был ее видеть, это работа автора топика. в конце концов я их объединила.

3
30 июля 2007 года
Green
4.8K / / 20.01.2000
Цитата: Vedrus

А компилятор си думает по другому:
Код:
//void main()
//{
00401090    push    ebp
00401091    mov ebp,esp
00401093    sub esp,40h
00401096    push    ebx
00401097    push    esi
00401098    push    edi
00401099    lea edi,[ebp-40h]
0040109C    mov ecx,10h
004010A1    mov eax,0CCCCCCCCh
004010A6    rep stos    dword ptr [edi]
//goto l1;
004010A8    jmp         l1+2 (004010ac)
//f();
//f();
//f();
//l1: ;
//}


Типичная ошибка уже не начинающего, но ещё неопытного программиста - ставить жесткую зависимость между командами ЯВУ и ассемблера.
Такой прямой и универсальной зависимости нет, т.к. есть множество доп. факторов.

Код:
//void main ()
//{
//    if( f() ) {
00411A6E  call        f (411055h)
00411A73  movzx       eax,al
00411A76  test        eax,eax
00411A78  je          main+2Ch (411A7Ch)
//       return;
00411A7A  jmp         main+31h (411A81h)
//    }
//    f();
//}
00411A81  xor         eax,eax
...
00411A96  ret

Ой! Смотри, return - это тоже jmp! :D

или вот твой же код, но скомпилированный моим компилятором:
Код:
//void main ()
//{
00411A50  push        ebp  
00411A51  mov         ebp,esp
00411A53  sub         esp,0C0h
00411A59  push        ebx  
00411A5A  push        esi  
00411A5B  push        edi  
00411A5C  lea         edi,[ebp-0C0h]
00411A62  mov         ecx,30h
00411A67  mov         eax,0CCCCCCCCh
00411A6C  rep stos    dword ptr [edi]
//    goto l1;    
//    f();
//    f();
//    f();
//l1: ;
//}
00411A6E  xor         eax,eax
00411A70  pop         edi  
00411A71  pop         esi  
00411A72  pop         ebx  
00411A73  add         esp,0C0h
00411A79  cmp         ebp,esp
00411A7B  call        @ILT+935(__RTC_CheckEsp) (4113ACh)
00411A80  mov         esp,ebp
00411A82  pop         ebp  
00411A83  ret

Вообще jmp не вижу.

Ты ещё утверждаешь, что goto это jmp и от быстрее return? :D
Извини, но тогда ты просто некомпетентен... и дальнейший спор излишен...
Можно спорить о необходимости goto, но о его быстроте по сравнению с return... :D

Цитата: Vedrus

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


Не понял фразы, растолкуй.

3
30 июля 2007 года
Green
4.8K / / 20.01.2000
Цитата: OlgaKr
Taк я и написала об этом в своем посте, и к данному моменту никто еще не привел другого примера, когда гото лучше. Напрашивается вывод, что гото лучше, эффективней использовать для выхода из вложенных циклов. Тогда непонятно о чем тут вообще спорить можно.

http://forum.codenet.ru/showpost.php?p=164484&postcount=13


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

Согласись, что спасательная шлюпка - не лучший способ пересекать Атлантику. Если к тебя 15 (!) вложенных циклов , да еще и с таким жутким условием выхода, то может просто надо подумать над реализацией всего алгоритма, а не о том, что лучше использовать goto?

353
30 июля 2007 года
Nixus
840 / / 04.01.2007
goto необходим, когда стоит вопрос производительности (пример - синтаксические анализаторы). И думаю что, один лабел в функции читабельность не ухудшит. Пример:

Код:
int Init()
{
     if(!Init1(&pData1))
     {
          printf("Не проиден первый шаг инициализации.\n");
          goto shutdown;
     }

     if(!Init2(&pData2_0, &pData2_1))
     {
          printf("Не проиден второй шаг инициализации.\n");
          goto shutdown;
     }

    // ...

    // Выходим без ошибки.
    return 1;

shutdown:
    // Финализируем и выходим с ошибкой.
    Shutdown();
    return 0;
}

void Shutodown()
{
   if(pData1)
   {
        free(pData1);
        pData1 = NULL;
   }

   if(pData2_0)
   {
        free(pData2_0);
        pData2_0 = NULL;
   }

   if(pData2_1)
   {
        free(pData2_1);
        pData2_1 = NULL;
   }

   // ...
}


По-моему, подход с goto компактнее, намного легче читаем и более стабилен нежели ручная финализация и возвращение после неудачи.
3
30 июля 2007 года
Green
4.8K / / 20.01.2000
Необходим?!
Да тот код, который ты привел - это жуть.
Его можно сделать намного аккуратнее и уж тем более без goto. Обычно такие вещи обычно делаются с помощью цикла иннициализации. Я уже как-то рассказывал об этом на форуме.

Вопрос производительности?!
Может ты объяснишь, как goto влияет на производительность?
353
30 июля 2007 года
Nixus
840 / / 04.01.2007
Цитата: Green
Необходим?!
Да тот код, который ты привел - это жуть.
Его можно сделать намного аккуратнее и уж тем более без goto. Обычно такие вещи обычно делаются с помощью цикла иннициализации. Я уже как-то рассказывал об этом на форуме.


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

Цитата: Green

Вопрос производительности?!
Может ты объяснишь, как goto влияет на производительность?


Легко. Что быстрее переход на определнный адрес (goto) или засовывание параметров в стек, переход на определенный адрес и возвращение (вызов функции)?

И еще, вы сами синтаксический анализатор писали, чтобы так говорить? Очевидно, вы плохо знакомы с системным программировнием.

2
30 июля 2007 года
squirL
5.6K / / 13.08.2003
Цитата: Nixus
.... Очевидно, вы плохо знакомы с системным программировнием.



*уселся в первом ряду с пивом и чипсами*

3
30 июля 2007 года
Green
4.8K / / 20.01.2000
Цитата: Nixus
Код, пожалуйста, особено для ситуации, когда в функции передаются разные параметры в различных последовательностях. И обоснование, почему он читабельнее и аккуратнее. Иначе, буду расценивать, как пустую болтовню.


И так, приступим...

Глава 1, в которой рассказывается, что goto является симптомом плохой структурированности программы.

Ответь, для чего твоя функция Init() ? А что она делает?
Отвечу на вопрос, т.к. вижу это я, читатель твоего кода.
Эта функция для того, чтобы что-то иницивлизировать. А делает она следущее: инициализирует последовательно какие-то подсистемы, обрабатывает ошибки инициализации, выводит информацию об ошибках, вызывает деинициализацию. Странно, что ко всему этому она не варит кофе и не пылесосит.

Налицо ошибка структурирования: функция должна по возможности выполнять что-то одно и соотв-но называться.
Поэтому твоя функция - это на самом деле три зверя в одной шкуре:
1) инициализатор,
2) обработчик ошибок,
3) вывод инф.

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

Код:
int tryToInit()
{
    int error = Init();
    if (error != ERROR_OK) {
        // Финализируем и выходим с ошибкой.
        Shutdown();
        errorTextOutput(int error);
        return 0;
    }

    // Выходим без ошибки.
    return 1;
}

int Init()
{
    if ( !Init1(&pData1) )
        return ERROR_INIT1

     if(!Init2(&pData2_0, &pData2_1))
        return ERROR_INIT2

    // ...

    // Выходим без ошибки.
    return ERROR_OK;
}

void errorTextOutput(int error)
{
    printf( errorMsg[error] );
}

Объяснять про читабельность или сам видишь?

Глава 2, в которой сказано, как лучше ЭТО делать.

Как уже говорил, для инициализации подобного рода, когда есть множество последовательных и критичных инициализаций подсистем, используется пошаговая инициализация/деинициализация. Её использование делает инициализацию и обработку ошибок более гибкими и аккуратными. Так у тебя функуция Shutodown() очень сомнительна, т.к. деинициализация происходит не в обратной последовательности относительно инициализации, а что деинициализировать выясняется по косвеному признаку - "то что не ноль", а если надо деинициадизировать, даже если ноль?

Я уже описывал схему такой пошаговой инициализации/деинициализации. Поищи на форуме.

Цитата: Nixus

Легко. Что быстрее переход на определнный адрес (goto) или засовывание параметров в стек, переход на определенный адрес и возвращение (вызов функции)?


Во первых, для невнимательных, я ещё раз повторяю:
return - это не ret,
goto - это не jmp,
вызов функции - это не call.

Очевидно, вы плохо знакомы с программировнием на языках программирования. :D

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

353
30 июля 2007 года
Nixus
840 / / 04.01.2007
Код, конечно, замечательный, но...
Во-первых, зачем вводить лишние функции и константы, когда можно ввести одну метку? К тому же при добавлении нового этапа, придется добавлять строку в таблицу строк, создавать новую константу, т.е. прыгать по коду. Чтобы даже чуть-чуть изменить сообщение об ошибке, нужно будет взять номер ошибки и вруную считать строки в таблице, чтобы найти нужную строчку. Это все факторы, облегчающие рефакторинг?

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

Далее...
Если вы думаете, что goto реализуется не через jmp, а вызов и возвращение из функции - не через call и ret, то читаем доку по ассемблеру и смотрим как компиляторы генерируют код.

Насчет оптимизации...
Взгляните на вывод генераторов flex и bison и посчитайте количество goto. Они там введены не от хорошей жизни. Это единтсвенный достаточно эффективный и быстрый способ огранизовать сложное ветвление.
Другое дело, что такие задачи - редкость, но говорить, что goto совсем не нужен - в корне не верно.
3
31 июля 2007 года
Green
4.8K / / 20.01.2000
Цитата: Nixus
Код, конечно, замечательный, но...
Во-первых, зачем вводить лишние функции и константы, когда можно ввести одну метку?


А зачем, вообще, писать на ЯВУ ?
А ответ на твой вопрос в начале моего предыдущего поста. Читал?

Цитата: Nixus

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


Ну строку придется добавлять все равно, не так ли?
Константу можно не создавать, это всего лишь пример реализации и "а если" можно придумать сколько угодно. Возвращай строку, а не номер ошибки, но это уже будет некрасиво.

Цитата: Nixus

Чтобы даже чуть-чуть изменить сообщение об ошибке, нужно будет взять номер ошибки и вруную считать строки в таблице, чтобы найти нужную строчку.


:D
М-да...
А давать нормальные, значимые, имена не пробовал?
И с чего ты взял, что надо что-то считать в таблице?
В конце концов, я привел лишь пример соотв. кода ошибки и его сообщения.
Кроме того, это уже вопрос не по goto, а по организации хранения текстовых сообщений. Так вот весь output должен быть отвязан от бизнес-логики. Хочешь с этим поспорить?

Цитата: Nixus

Это все факторы, облегчающие рефакторинг?


Да, разгранечение прав и ответственности - методы облегчающие как рефакторинг, так и развитие кода.


Цитата: Nixus

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


А я могу выводить сообщения на 30 языках мира, что в твоем коде вообще не возможно.
Я ещё раз повторяю: весь output должен быть отвязан от бизнес-логики и это уже вопрос не по goto.
Я могу придумать и генерацию сообщений на основании конкретной инф. ао аремя инициализации. И поверь, эта генерация не будет зашита в код бизнес-логики.

Цитата: Nixus

Далее...
Если вы думаете, что goto реализуется не через jmp, а вызов и возвращение из функции - не через call и ret, то читаем доку по ассемблеру и смотрим как компиляторы генерируют код.


Ну так посмотри! Несколькими постами выше.
Тебе перечислить некоторые варианты, когда вызов функции - это не call, return - это не ret, а goto - это не jmp, или сам попытаешься?

Цитата: Nixus

Насчет оптимизации...
Взгляните на вывод генераторов flex и bison и посчитайте количество goto. Они там введены не от хорошей жизни. Это единтсвенный достаточно эффективный и быстрый способ огранизовать сложное ветвление.


1) при чем тут оптимизация?
2) уто сказал, что единстыкнный?
3) кто сказал, что эффективный?
4) а зачем организовывать таким образом "сложное ветвление"?

Цитата: Nixus

Другое дело, что такие задачи - редкость, но говорить, что goto совсем не нужен - в корне не верно.


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

353
31 июля 2007 года
Nixus
840 / / 04.01.2007
Вы так и не объяснили, почему goto в том случае делает программу менее читабельной. И каков критерий аккуратности.

Цитата: Green

Кроме того, это уже вопрос не по goto, а по организации хранения текстовых сообщений. Так вот весь output должен быть отвязан от бизнес-логики. Хочешь с этим поспорить?
...
А я могу выводить сообщения на 30 языках мира, что в твоем коде вообще не возможно.



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

Цитата: Green

Ну так посмотри! Несколькими постами выше.
Тебе перечислить некоторые варианты, когда вызов функции - это не call, return - это не ret, а goto - это не jmp, или сам попытаешься?


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

Цитата: Green

1) при чем тут оптимизация?
2) уто сказал, что единстыкнный?
3) кто сказал, что эффективный?
4) а зачем организовывать таким образом "сложное ветвление"?


Предложте более элегантное решение. Популязировать чужие парадигмы и я могу, а что толку?

Цитата: Green

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


Я вам привел одну задачу, где оно оправдано. Вы с ней знакомы?

5.7K
31 июля 2007 года
Vedrus
49 / / 29.10.2006
[quote=OlgaKr]
Если использовать goto там, где он не нужен - то считается криво и необходимости никакой нет.
[/quote]
Согласн

[quote=Green]
Ты ещё утверждаешь, что goto это jmp и от быстрее return?
[/quote]
По поводу return'а я уже признал свою ошибку. По поводу goto/jmp, ты скорее всего используешь оптимизирующий компилятор, естественно он вырезает функции, которые вообще нигде не вызываются. В реальных задачах (когда обе ветки управление получают) goto - это jmp.

Пример конкретный привести не мог, т.к. с задачей не сталкивался, когда goto предпочтителен. Спасибо Nixus, одну из таких привёл.
26K
31 июля 2007 года
newonder
12 / / 31.07.2007
Уважаеый green, вы зря упорствуете. Вот один из примеров когда необходимо использовать goto (это учебный пример) - реализция машины тьюринга. Попробуйте сделать эту машину для сложения, например, двух чисел на любом из АЯВУ.

А я, пожалуй, присоеденюсь к squirl-у. Надеюсь он чипсами поделится. ;) Пиво своё.
5.7K
31 июля 2007 года
Vedrus
49 / / 29.10.2006
Напишите этот кусочек кода не криво плиз, а то я никак не соображу как :)


Код:
for(int i=0;i<n1;++i) {
  for(int j=0;j<n2;++j) {
    if(come_condition1) goto next1;
    for(int k=0;k<n3;++k) {
      if(come_condition2) goto next2;
    }
    // some code
  }
  next2:
  // some code
}
next1:
// some code
5.7K
31 июля 2007 года
Vedrus
49 / / 29.10.2006
А всё-таки насчёт return'а я был прав! Смотрите код:
Обработка ошибок с использованием GOTO
Код:
// open_control() -- [C]
// Open a file and assign it a control object.
// Returns the control object on success, or NULL on failure.

struct Control * open_control(const char *fname)
{
    struct Control *  ctl = NULL;
    FILE *            fp =  NULL;

    // 1. Allocate a control object
    ctl = malloc(sizeof(struct Control));
    memset(ctl, 0, sizeof(struct Control));
    if (ctl == NULL)                        // E-1
        goto fail;

    // 2. Save the file name
    ctl->name = malloc(strlen(fname)+1);
    if (ctl->name == NULL)                  // E-2
        goto fail;
    strcpy(ctl->name, fname);

    // 3. Open the named file
    fp = fopen(fname, "rb");
    if (fp == NULL)                         // E-3
        goto fail;
    ctl->fp = fp;

    // 4. Read the file header block
    if (!read_header(ctl))                  // E-4
        goto fail;

    // Return success
    return ctl;

fail:
    // Failure occurred, clean up allocated resources
    if (ctl != NULL)
    {
        if (ctl->fp != NULL)
            fclose(ctl->fp);                // H-3
        if (ctl->name != NULL)
            free(ctl->name);                // H-2
        free(ctl);                          // H-1
    }

    // Return failure
    return NULL;
}

Без использования GOTO
Код:
// open_control() -- [C, version 3, without gotos]
// Open a file and assign it a control object.
// Returns the control object on success, or NULL on failure.

struct Control * open_control(const char *fname)
{
    struct Control *  ctl = NULL;
    FILE *            fp =  NULL;
    int               err = 0;

    // 1. Allocate a control object
    ctl = malloc(sizeof(struct Control));
    memset(ctl, 0, sizeof(struct Control));
    if (ctl == NULL)                        // E-1
        err = 1;

    // 2. Save the file name
    if (err == 0)
    {
        ctl->name = malloc(strlen(fname)+1);
        if (ctl->name == NULL)              // E-2
            err = 2;
        else
            strcpy(ctl->name, fname);
    }

    // 3. Open the named file
    if (err == 0)
    {
        fp = fopen(fname, "rb");
        if (fp == NULL)                     // E-3
            err = 3;
        else
            ctl->fp = fp;
    }

    // 4. Read the file header block
    if (err == 0)
    {
        if (!read_header(ctl))              // E-4
            err = 4;
    }

    // Check for success
    if (err == 0)
        return ctl;

    // Failure, clean up
    if (err > 3)
        fclose(ctl->fp);                    // H-3
    if (err > 2)
        free(ctl->name);                    // H-2
    if (err > 1)
        free(ctl);                          // H-1

    return NULL;
}

Что скажете, мистер Green? Так что приношу самому себе же свои глубочайшие извинения. Я всё-таки был прав.

Хотя вот ещё интересный вариант, но тоже спорный.
SEH
Код:
void write3(Resource dest, Item[] data)
{
    try
    {
        dest.acquire();
        dest.write(data[0]);
        dest.write(data[1]);
        dest.write(data[2]);
    }
    catch (ResourceException ex)
    {
        // Failure occurred, clean up
        log.error(ex);
        dest.reset();
    }
    finally
    {
        // Always executed
        dest.release();
    }
}


Кстати, у нас в следующем году юбилей. 50 лет люди грызутся по поводу GOTO. Без балды. Побухаем...
353
31 июля 2007 года
Nixus
840 / / 04.01.2007
Синтаксический анализатор и машина Тьюринга - это конечные автоматы. goto оправдывает себя при программировнии КА, делая код легче и компактнее. В некоторых случаях даже понятнее.
241
01 августа 2007 года
Sanila_san
1.6K / / 07.06.2005
Цитата: 3A3-968M
Возможно, но это предположение умерщвляется следующей задачей:
"Выход из множества вложенных циклов одновременно"

Ни разу не умерщвляется. Поместить циклы в процедуру/функцию и выйти из неё по условию.

241
01 августа 2007 года
Sanila_san
1.6K / / 07.06.2005
Цитата: Nixus
Синтаксический анализатор и машина Тьюринга - это конечные автоматы. goto оправдывает себя при программировнии КА, делая код легче и компактнее. В некоторых случаях даже понятнее.

Не далее как в январе написал приятельнице КА без единого Goto, паче того, не выходя за рамки стандартного Паскаля.

Вообще странный спор. В Java слово goto зарезервировано, но ничего не делает. Для C# в MSDN приводится красивый пример того, как делать не надо:

Код:
// statements_goto_switch.cs
using System;
class SwitchTest
{
    static void Main()
    {
        Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");
        Console.Write("Please enter your selection: ");
        string s = Console.ReadLine();
        int n = int.Parse(s);
        int cost = 0;
        switch (n)
        {
            case 1:
                cost += 25;
                break;
            case 2:
                cost += 25;
                goto case 1;
            case 3:
                cost += 50;
                goto case 1;
            default:
                Console.WriteLine("Invalid selection.");
                break;
        }
        if (cost != 0)
        {
            Console.WriteLine("Please insert {0} cents.", cost);
        }
        Console.WriteLine("Thank you for your business.");
    }
}
Вот яркий пример неоправданного использования Goto.

А к вопросу о вложенных циклах вот навскидку пример, правда, на VB.NET.
Код:
[COLOR="Blue"]Function[/COLOR] NestedCycles(ByVal ParameterArray [COLOR="Blue"]As Integer[/COLOR](), [COLOR="Blue"]ByVal[/COLOR] var [COLOR="Blue"]As Integer[/COLOR]) [COLOR="Blue"]As Integer
        For[/COLOR] i [COLOR="Blue"]As Integer[/COLOR] = 0 [COLOR="Blue"]To[/COLOR] 100
            [COLOR="Blue"]For[/COLOR] j [COLOR="Blue"]As Integer[/COLOR] = 0 [COLOR="Blue"]To[/COLOR] 100
                [COLOR="Blue"]For[/COLOR] k [COLOR="Blue"]As Integer[/COLOR] = 0 [COLOR="Blue"]To[/COLOR] 100
                    [COLOR="Blue"]For[/COLOR] l [COLOR="Blue"]As Integer[/COLOR] = 0 [COLOR="Blue"]To[/COLOR] 100
                        [COLOR="DarkGreen"]'...[/COLOR]
                        [COLOR="Blue"]For[/COLOR] z As Integer = 0 [COLOR="Blue"]To[/COLOR] 100
                            [COLOR="Blue"]If[/COLOR] var = ParameterArray(i, j, k, l, m, n, o, p, r, s, t, u, v, w, x, y, z) [COLOR="Blue"]Then
                                Return[/COLOR] var
                                [COLOR="Blue"]Exit Function[/COLOR]
                            [COLOR="Blue"]End If
                        Next[/COLOR]
                        [COLOR="DarkGreen"]'...[/COLOR]
                    [COLOR="Blue"]Next
                Next
            Next
        Next
    End Function[/COLOR]
Аналогичным способом можно выйти из любого места функции. Кстати, к вопросу о быстродействии. Надеюсь, все в курсе, что в .Net код сначала компилируется в MSIL, а уж потом, при запуске приложения - в машинный код. Отсюда вопрос: в какой код компилируется MSIL-версия первого примера?
353
01 августа 2007 года
Nixus
840 / / 04.01.2007
Цитата: Sanila_san
Не далее как в январе написал приятельнице КА без единого Goto, паче того, не выходя за рамки стандартного Паскаля.


Я не сказал, что написать без goto КА нельзя. Вопрос в том насколько использование и не использование goto повлияет на размер кода, читабельность и производительность.

5.7K
01 августа 2007 года
Vedrus
49 / / 29.10.2006
MSDN тоже люди и тоже с противоречивыми мыслями писали. По поводу кода «как не нужно делать». Покажите, тогда как нужно! Быстрее и нагляднее у вас не получится. А уповать на то, что в автоматах бесконечный цикл с селектором не многим медленнее не правильно, так как в трансляторах таких автоматов туева хуча.

По поводу циклов по-моему уже давно проехали.

Цитата:

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


(с) amirul

Цитата:

Существует два правила, когда goto практически не нарушает читабельность кода
1. Переходить можно только вперед
2. Заходить в блоки категорически нельзя (либо оставаться либо выходить)

Неиспользование goto даже там где это оправдано - это что то типа религии. Лучше не спорь с религиозными людьми - все равно ничего им не докажешь.


(c) Serg

241
01 августа 2007 года
Sanila_san
1.6K / / 07.06.2005
Цитата: Nixus
Вопрос в том насколько использование и не использование goto повлияет на размер кода, читабельность и производительность.

Вдумчиво смотрим disassembly, любезно опубликованную тов. Green 30.07.2007 в 06:57. После вдумчивого разглядывания кода расскажите мне, где и как goto влияет на производительность? Сказано же: goto <> jmp. Ясно, что при написании кода на ЯВУ нельзя заранее предсказать, как он будет отображён в машинные коды. Если же речь идёт о таких вещах, как Java или .Net, то тут вообще невозможно определить результат отображения. Как в этом случае можно рассуждать о производительности?

Замечено, что создание экземпляра класса занимает времени в десятки раз большее, чем выход из цикла или условия. Ок, допустим, что в Паскале мы не создаём экземпляры классов. Но множество вложенных циклов – это чем можно оправдать? Что вы делаете такими конструкциями? В самом деле, обход десятимерного массива может показаться удобным делать при помощи десяти вложенных циклов, но вот вопрос: как это отлаживать? А если массив трёхсотмерный? Или вообще динамический? Что тогда?

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

К вопросу о читабельности я привёл пример из MSDN на C#. Вроде бы всё понятно, и читается легко. Однако легко ли навскидку сказать, сколько будет стоить кофе в случае 3? В этом примере несложно, поскольку лёгкий пример. Теперь допустим, что вместо += 25 у нас везде стоит [FONT="Courier New"]= sin(tan(cost))[/FONT]. Или вообще что-то вроде new [FONT="Courier New"]CashMachineEmulator[/FONT]. Вы видите здесь оптимизацию? Я вижу здесь ресурсоёмкую операцию. Да, пример сам по себе не показательный, но хорошая практика состоит в том, чтобы заранее избегать потенциально плохих конструкций. Принципиально возможно вовсе обойтись без Goto. Вот, что говорит классик.[QUOTE=Niklaus Wirth]As a corollary, a language must allow, encourage, or even enforce formulation of programs as properly nested structures, in which properties of the whole can be derived from properties of the parts. Consider, for example, the specification of a repetition R of a statement S. It follows that S appears as a part of R. We show two possible forms:
R0: while b do S end R1:
repeat S until b

The key behind proper nesting is that known properties of S can be used to derive properties of R. For example, given that a condition (assertion) P is left valid (invariant) under execution of S, we conclude that P is also left invariant when execution of S is repeated. This is formally expressed by Hoare’s rules

{P & b} S {P} implies {P} R0 {P & ¬b}
{P} S {P} implies {P} R1 {P & b}


[COLOR="DarkRed"]If, however, S contains a go to statement, no such assertion is possible about S, and therefore neither any deduction about the effect of R. This is a great loss. Practice has indeed shown that large programs without go to are much easier to understand, and that it is very much easier to give any guarantees about their properties.[/COLOR][/QUOTE]Выделение цветом моё.

240
01 августа 2007 года
aks
2.5K / / 14.07.2006
=)))
Ну чтож вы уперлись в автоматы со своим goto. Все это вполне качественно, и что самое главное легко читаемо и поддерживаеммо, решается без него. Для чего придумывали языки высокого уровня, для чего существуют современные парадигмы программирования, которыми вы вроде и пытаетесь пользоваться, а потом тут же нарушаете. Ну вы же не в машинных кодах пишете в конце концов и не на ассеблере. Зачем пытаться ассоциировать код с ассемблерными командами (когда языки высокого уровня сремятся быть как можно абстрагированней от аппаратной платформы и т.п.). Ну не нужна эта преждевременная оптимизация - она только заранее всю структуру программы испортит, послушайте Кнута (да и Green тоже упоминал), он умный дядька и опыта у него куда побольше вашего. =))
Такое ощущение, что не приходилось сталкиваться с какой то более менее объемной задачей, а потом разруливать последствия вот такого вот стиля программирования.

Цитата:

Кстати, одна из причин по которой мне не нравится та же Java - так это то, что они выкинули очень мощные, но естественно опасные инструменты. Это потакание глупости и скорее регресс, чем прогресс.
(с) amirul

Цитата:
Существует два правила, когда goto практически не нарушает читабельность кода
1. Переходить можно только вперед
2. Заходить в блоки категорически нельзя (либо оставаться либо выходить)

Неиспользование goto даже там где это оправдано - это что то типа религии. Лучше не спорь с религиозными людьми - все равно ничего им не докажешь.
(c) Serg


Ну и что эти цитаты дают? ну лишний повод упереться. =)
Вот в ответ тоже цитата:
http://khpi-iip.mipk.kharkiv.edu/library/extent/dijkstra/pp/ewd215.html

Дейкстра к слову куда более авторитетный и уважаемый в программистской среде человек.

241
01 августа 2007 года
Sanila_san
1.6K / / 07.06.2005
Цитата: Vedrus
По поводу кода &#171;как не нужно делать&#187;. Покажите, тогда как нужно! Быстрее и нагляднее у вас не получится.

Виноват, что и быстрее чего? Быстрее написать, быстрее отладить?

А как нужно? Ну, хотя бы так:

Код:
// statements_goto_switch.cs
using System;
class SwitchTest
{
    static void Main()
    {
        Console.WriteLine("Coffee sizes: 1=Small 2=Medium 3=Large");
        Console.Write("Please enter your selection: ");
        string s = Console.ReadLine();
        int n = int.Parse(s);
        int cost = 25;
        switch (n)
        {
            case 1:
                break;
            case 2:
                cost += 50;
                break;
            case 3:
                cost += 75;
                break;
            default:
                Console.WriteLine("Invalid selection.");
                break;
        }
        if (cost != 0)
        {
            Console.WriteLine("Please insert {0} cents.", cost);
        }
        Console.WriteLine("Thank you for your business.");
    }
}
Пример, скажем прямо, не бог весть какой показательный, но даже такой тупой вариант читается легче. Более того, здесь явно написано, чему будет равно значение cost в случаях 2 и 3, а по аналогии - в случаях 20 и 30. Ведь ясно, что если goto будет выкидывать в код, расположенный на 500 строк ниже (что легко) или на 200 строк выше (что тоже запросто), путаница возникнет обязательно.
240
01 августа 2007 года
aks
2.5K / / 14.07.2006
Цитата: Sanila_san
После вдумчивого разглядывания кода расскажите мне, где и как goto влияет на производительность? Сказано же: goto <> jmp. Ясно, что при написании кода на ЯВУ нельзя заранее предсказать, как он будет отображён в машинные коды.


А если еще код или часть кода пишется исходя из того что он будет работать на разных аппаратных платформах (а большинство ЯВУ это позволяют), то о каком вобще отображении кода на ассемблер конкретного железа может идти речь? )

26K
01 августа 2007 года
newonder
12 / / 31.07.2007
Господа, послушайте. Ну почему вы всё меряете общим аршином? Есть задачи где goto неуместен, есть задачи где без него не обойтись. Если вы пишете на делфе какую-нить прогу, то там да, возможно goto не нужен, но зачем заявлять что goto это зло? Есть задачи (обратим свой взгляд на КА) где без goto ну никак не обойтись. А эта область достаточно востребованная. Да вы и сами программируете на АЯВУ, в коде которых есть эти самые goto. Это тоже самое что спорить что ООП - это панацея от всех бед. Для каждой задачи есть своё решение, и если, извините меня, через ж... делать, то вы сделаете, и можете себе медальку вешать на грудь, но ваш подход просто покажет вашу ограниченность и неспособность адекватно оценивать ситуацию и поставленную задачу.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог