сделайте {…} в то время как (ложь)

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

<return-type> function(<params>)
{
 <initialization>

 do
 {
   <main code for function>
 }
 while(false);

 <tidy-up & return>
}

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

117
задан Gordon Gustafson 22 February 2010 в 22:18
поделиться

20 ответов

Вы можете разбить из сделать {...} while (false) .

169
ответ дан 24 November 2019 в 02:00
поделиться

Попробуйте использовать атрибуты checkingaccount и saving saccount . Тот, кто это, не взорвется.

-121--2995464-

Я установил 2010, а 2008 уже установлен. У меня были тонны повешений, крушений и общих неисправностей. Переустановка 2008 не помогла, пока я не удалил все следы 2010 года из реестра.

-121--2666440-

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

0
ответ дан 24 November 2019 в 02:00
поделиться

Я работаю с Adobe InDesign SDK, и в примерах InDesign SDK почти все функции написаны таким образом. Это связано с тем, что функции обычно очень длинные. Где вам нужно выполнить QueryInterface (...), чтобы получить что-либо из объектной модели приложения. Таким образом, обычно за каждым QueryInterface следует , если не прошел успешно, остановитесь.

0
ответ дан 24 November 2019 в 02:00
поделиться

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

Я также видел, как эта конструкция использовалась в смешанных средах C / C ++ как исключение для бедняков. «Do {} while (false)» с «break» можно использовать для перехода к концу блока кода, если в цикле встречается что-то, что обычно требует исключения.

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

0
ответ дан 24 November 2019 в 02:00
поделиться

Это просто: очевидно, вы можете выйти из ложного цикла в любой момент, используя оператор break . Кроме того, блок do является отдельной областью (что также может быть достигнуто только с помощью {...} ).

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

<return-type> function(<params>)
{
 <initialization>

 <main code for function using "goto error;" if something goes wrong>

 <tidy-up in success case & return>

 error:

 <commmon tidy-up actions for error case & return error code or throw exception>
}

(В стороне: Конструкция do-while-false используется в Lua для поиска отсутствующего оператора continue .)

2
ответ дан 24 November 2019 в 02:00
поделиться

Сколько лет было автору?

Я спрашиваю, потому что однажды в конце 80-х я наткнулся на какой-то код на Фортране, который делал это в реальном времени. Оказывается, это действительно хороший способ имитировать потоки в ОС, в которой их нет. Вы просто помещаете всю программу (ваш планировщик) в цикл и вызываете свои «подпрограммы потоков» одну за другой. Сами подпрограммы потоков представляют собой циклы, которые повторяются до тех пор, пока не произойдет одно из ряда условий (часто одно из которых время прошло). Это «кооперативная многозадачность», в которой каждый поток должен время от времени отказываться от ЦП, чтобы другие не истощались. Вы можете вложить циклические вызовы подпрограммы для имитации приоритета потока диапазоны.

1
ответ дан 24 November 2019 в 02:00
поделиться

В дополнение к уже упомянутым примерам «goto» в определении макроса иногда используется идиома do ... while (0), чтобы обеспечить скобки в определении и при этом заставить компилятор работать с добавлением точки с запятой в конец вызова макроса.

http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/52f670f1292f30a4?tvc=2&q= while+ (0)

1
ответ дан 24 November 2019 в 02:00
поделиться

Это забавно. Вероятно, внутри цикла есть разрывы, как говорили другие. Я бы сделал это так:

while(true)
{
   <main code for function>
   break; // at the end.
}
-1
ответ дан 24 November 2019 в 02:00
поделиться

Я думаю, это сделано для использования операторов break или continue. Что-то вроде логики кода "goto".

2
ответ дан 24 November 2019 в 02:00
поделиться

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

Его главный недостаток по сравнению с идиомой C ++ заключается в том, что он не приводит в порядок, если в теле возникает исключение. В C не было исключений, так что это не было проблемой, но это стало плохой привычкой в ​​C ++.

6
ответ дан 24 November 2019 в 02:00
поделиться

Это очень распространенная практика. В C . Я пытаюсь думать об этом так, как будто вы хотите солгать себе способом: «Я не использую goto ». Если подумать, нет ничего плохого в аналогичном использовании goto . Фактически это также уменьшило бы уровень отступа.

Тем не менее, я заметил, что очень часто петли do .. while имеют тенденцию к росту. А затем они получают внутри if и else , что делает код не очень читабельным, не говоря уже о тестируемом.

Те делают .. пока обычно предназначены для очистки . Во что бы то ни стало, я бы предпочел использовать RAII и вернуть ранний из функции short . С другой стороны, C не предоставляет вам столько удобства, как C ++ , что делает do .. while одним из лучших подходов для создания уборка.

7
ответ дан 24 November 2019 в 02:00
поделиться

Это просто извращение , а , чтобы получить семантику goto-tidy-up без использования слова goto.

Это плохой тон, потому что, когда вы используете другие циклы внутри внешнего , а разрывы становятся неоднозначными для читателя. «Это должно идти к выходу? Или это предназначено только для выхода из внутреннего цикла?»

10
ответ дан 24 November 2019 в 02:00
поделиться

Используется этот трюк программистами, которые слишком стесняются использовать явный goto в своем коде. Автор приведенного выше кода хотел иметь возможность сразу перейти к точке «очистить и вернуть» из середины кода. Но они не хотели использовать метку и явный goto . Вместо этого они могут использовать разрыв внутри тела вышеуказанного «ложного» цикла для достижения того же эффекта.

7
ответ дан 24 November 2019 в 02:00
поделиться

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

Это может сделать утомительное дерево if / else-if намного более легким для чтения, просто имея необходимость прерывать работу всякий раз, когда достигается точка выхода, а остальная часть логики вставляется позже.

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

20
ответ дан 24 November 2019 в 02:00
поделиться

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

do {
    if (!condition1) break;
    some_code;
    if (!condition2) break;
    some_further_code;
    // …
} while(false);
2
ответ дан 24 November 2019 в 02:00
поделиться

Прерывание как goto, вероятно, является ответом, но я предложу еще одну идею.

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

Помните, что хотя последний C ++ допускает {...} где угодно, это не всегда так.

24
ответ дан 24 November 2019 в 02:00
поделиться

Многие отмечают, что его часто используют вместе с break как неудобный способ написания "goto". Возможно, это верно, если он написан непосредственно в функции.

В макросе, напротив, do { something; } while (false) - это удобный способ ЗАПРЕТИТЬ точку с запятой после вызова макроса, при этом абсолютно никакая другая лексема не должна следовать за ней.

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

.
119
ответ дан 24 November 2019 в 02:00
поделиться

Да, взгляните на pg _ dump и pg _ restore

http://www.postgresql.org/docs/current/static/app-pgdump.html

http://www.postgresql.org/docs/current/static/app-pgrestore.html

-121--4903683-

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

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

-121--2913789-

Я видел такой код, чтобы вы могли использовать break в качестве goto сортов.

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

Это надуманный способ имитировать GOTO, так как эти два практически идентичны:

// NOTE: This is discouraged!
do {
    if (someCondition) break;
    // some code be here
} while (false);
// more code be here

и:

// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here

С другой стороны, оба эти действия действительно должны выполняться с помощью ifs:

if (!someCondition) {
    // some code be here
}
// more code be here

Хотя вложенность может стать немного уродливой, если вы просто превратите длинную строку forward-GOTOs во вложенные ifs. Однако настоящий ответ - это правильный рефакторинг, а не подражание архаичным языковым конструкциям.

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

На самом деле, я не знаю ни одного Си-подобного языка, где do/while было бы идиоматическим решением для чего-либо.

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

0
ответ дан 24 November 2019 в 02:00
поделиться

Другая причина, о которой я могу думать, это то, что он украшает фигурные скобки, тогда как я верить в новый стандарт C ++, голые фигурные скобки недопустимы (ISO C их не любит). Иначе заглушить статический анализатор вроде пуха.

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

См. Тривиальный цикл Do While и Скобки хороши из C2.

Чтобы прояснить мою терминологию (которая, как мне кажется, следует стандартному использованию):

Открытые фигурные скобки :

init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();

Пустые фигурные скобки (NOP):

{}

например.

while (1)
   {}  /* Do nothing, endless loop */

Блок :

if (finished)
{
     closewindows(&windows);
     freememory(&cache);
}

, который станет

if (finished)
     closewindows(&windows);
freememory(&cache);

, если скобки будут удалены, тем самым изменяя поток выполнения, а не только область локальных переменных. Таким образом, не «отдельно стоящий» или «голый».

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

0
ответ дан 24 November 2019 в 02:00
поделиться
Другие вопросы по тегам:

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