Яка мета “;” в кінці циклу for?


76

Я знайшов такий код:

Суть функції полягає в тому, щоб перевірити, чи є число простим чи ні.

Я не розумію, чому for-loop має ;кінець:

Без цього код не працює належним чином.

Яке пояснення?


48
Цикл for має в кінці крапку з комою, оскільки автор ЗЛИЙ! У таких ситуаціях воно повинно йти самостійно.
sh1

21
@ sh1 Або, якщо автор хоче, щоб весь цикл був у одному рядку, його { }можна було б використати замість того, ;щоб задокументувати, що цикл навмисно має порожнє тіло і не включати жодного з наступних рядків.
Eliah Kagan

22
@EliahKagan, іноді, коли я відчуваю, що хочу підкреслити порожнечу тіла циклу, я напишу for (...) continue;.
sh1

8
@coredump Але дві проблеми з крапкою з комою, використані таким чином, (1) полягають у помилці, яку якийсь добросовісний розробник одного дня може видалити; і (2) якщо ви цього не бачите, ви очікуєте, що твердження під ним буде тим, що буде "зациклено". Останнє становить особливу небезпеку, оскільки програмісти вчаться не звертати особливого повідомлення з крапкою з комою в кінці рядка; так само, як люди, які читають, як правило, не помічають, якщо речення не закінчується
крапкою

6
@ Marco13 Чому автоматично припускають, що оригінальний автор невіглас? Ви ненавидите такий вид написання, дуже добре. Але ви знайдете багато людей, які віддають перевагу forциклічному підходу: врешті-решт, існує ініціалізація, умова зупинки та ітерація, що природно виражається forконструкцією. Ви не згодні, але я впевнений, що автор знає, що таке whileпетля. До речі, саме тому вам потрібні правила кодування в команді.
coredump

Відповіді:


89

Це означає те саме, що:


7
І це набагато кращий спосіб написати порожнє тіло циклу (хоча запис {}в один рядок, можливо, візуально простіший підказка до порожнього тіла). Якби не застарілий код, мові було б краще без ;правила порожнього оператора. Те, ;що є обов’язковим після do ... while(...), теж дурне, але принаймні там я бачив його розумне використання.
Марк ван Левен

5
@MarcvanLeeuwen Я вважаю ;більш читабельним. Порожній блок виглядає як аварія, як програміст просто забув заповнити тіло. Порожнє твердження дає зрозуміти його наміри.
Пол

19
@Paulpro, я вважаю, що і те, і інше є потенційними помилками і for (...) { /* empty block */ }є чіткішим, ніж обидва, наскільки демонструє, що це навмисно.
atk

2
Я не Cпрограміст, але чому, мабуть, це робити корисно?
Ітан Бірлейн,

6
@EthanBierlein "робота" виконується за допомогою тверджень всередині ( ); суть цього циклу полягає в тому, щоб отримати countв результаті певне значення, засноване наzahl
MM

53

Цикл for має for ключове слово, за яким слідують дужки, що містять три необов’язкові вирази, розділені крапками з комою, а потім тіло, яке виконується на кожній ітерації циклу.

Метою циклу for у вашому прикладі є встановлення значення count, яке буде порівняно з zahlнаступним оператором if. Це досягається у виразах з крапкою з комою, тому тілу циклу не потрібно нічого робити.

Оскільки цикл не повинен нічого робити, він використовує порожній оператор як своє тіло.

Якби ;кінець у кінці було пропущено і ніяких інших змін не було зроблено, тоді оператор if після циклу for сам би став тілом циклу for. (Це не призначено і призведе до порушення програми, як ви вже зазначали.)

Однак зробити ;тему свого циклу єдиним на одному рядку - це не єдиний спосіб написати порожнє тіло циклу, і це, мабуть, не найбільш розумний спосіб це зробити. Це чудово працює, але проблема в тому, що інші читачі - і, можливо, той самий програміст, який повертається до проекту пізніше - можуть задуматися, чи насправді це була помилка. Зрештою, досить часто набирають крапки з комою в кінці рядків під час кодування мовою в стилі С, тому легко ввести додатковий, де він не належить.

Інша проблема полягає в тому, що в коді , де петля одна лінія з , ;як його тіло обраний стиль, що важко розпізнати , коли хто - то на самому справі вже зробив помилку, вважаючи а ;коли один не належить.

Тому ці альтернативи можуть бути кращими:

  • ставлячи ;, з відступом, на наступному рядку - як підказує sh1
  • запис тіла циклу як порожній блок { }, а не як порожній оператор
  • створення тіла циклу continue;заявою, яка просто змушує цикл переходити до наступної ітерації (що те саме, що відбувається, коли тіло циклу порожнє) - також, як пропонує sh1

4
Хоча я можу погодитися з ;і {}, але я знайшов би continue;надзвичайно дивно. Мені це здавалося б так, ніби хтось очікував на continueзовнішній цикл чи щось інше. Безумовно, момент WTF, і ви хочете уникати їх у коді. Я б сказав, що {}фіксує намір найбільш читабельним чином.
Енджу більше не пишається SO

5
Інший варіант (який можна поєднати з іншими) - це вставити коментар:, for (...) /* do nothing */ ;щоб було зрозуміло, що він навмисний.

2
Я б додав до альтернатив, що збільшують змінну всередині циклу , наприклад:for(count=2; zahl % count != 0 && zahl >= count;) ++count;
Масса

3
@Massa - forцикл вважається одним за визначенням; експорт інкрементатора з циклу не дає жодних підстав використовувати forпроти whileбудь-якого.

@vaxquis у вас все ще є ініціалізація; Я б пішов з того, int count = 2; while( zahl % count && zahl >= count ) ++count;щоб почати все одно: D
Масса

41

Крапка з комою в кінці циклу for означає, що вона не має тіла. Без цієї крапки з комою C вважає, що ifоператор - це тіло циклу for.


4
+ int (PI / 3) для спотового спостереження, не вдаючись до суперечок "чи це хороша / погана практика кодування".

Однозначно +1, чітка, коротка фактична відповідь, яка не намагається визнати код поганим чи поганим стилем.
Валі

1
Цикл for однозначно має тіло. Це просто , що тіло складається виключно з заяви нуля, ;. Одинокий ;діє практично (якщо не насправді) у кожному місці, де дозволено висловлювання, оскільки одинокий ;- це нульовий вираз (що є твердженням).
користувач

22

Синтаксис forциклу ( оператор ітерації ) є

statementможе бути нульовим твердженням ( ;). C11 6.8.3 говорить

Нульовий оператор (що складається лише з крапки з комою) не виконує жодних операцій.

У параграфі 5 він наводить приклад

У фрагменті програми

null-оператор використовується для подання порожнього тіла циклу до оператора ітерації .

Те саме відбувається в

;використовується для подання порожнього тіла циклу до forоператора. Без ;оператора поруч із forциклом буде розглядатися його тіло і буде виконано.


1
+ int (PI / 3) для спотового спостереження, не вдаючись до суперечок "чи це хороша / погана практика кодування".

@vaxquis; Так, тому що питання стосується "чому for-loop має ;кінець?" . Йдеться не про "хороша практика чи ні?" .
хакі

17

На додаток до того, про що вже говорять інші чудові відповіді, я хотів би зазначити це

(тобто forцикл з порожнім оператором, що використовується для збільшення "лічильника") еквівалентний

це зробило б мету коду ще чіткішою, ніж деякі з перерахованих альтернатив: якщо відсутні коментарі, як у представленому випадку, цикл з порожнім оператором може збити з пантелику іншого програміста, який повинен підтримувати або використовувати код (як це було справа з ОП тут).

Контекст може допомогти розпізнати справжній обсяг висловлювання, але між forциклом з порожнім висловленням та whileциклом з висловлюванням останньому потрібно менше праці, щоб зрозуміти його обсяг.


1
Незначний підозрілий: це не є суто еквівалентом, оскільки у другій версії countзаявлено в більшому обсязі.
coredump

Я маю на увазі загалом ... тут countоголошено на початку функції в обох версіях.
coredump

2
@coredump: Беручи до уваги, що метою цього циклу - в даному конкретному випадку - досягти countправильного значення, щоб його можна було використовувати далі, countмає існувати в більшому обсязі, щоб це взагалі працювало і тому він точно еквівалентний. ( forОднак це все ще потворне зловживання циклом, і Федеріко має рацію, що це Правильний спосіб виразити залучену семантику.)
Мейсон Уілер,

@MasonWheeler Так, я думав про загальний випадок. Обидва насправді тут рівнозначні.
coredump

1
Чому цикл for незрозумілий? Я зрозумів, що цикл for є явним чином, щоб мати ініціалізацію, умову та ітераційний оператор, що логічно поєднуються. Ніколи не потрібно використовувати цикл for, але цей вигляд здавався розумним і чітко написаним.
Валі

12

Цикл ;after forпросто означає, що forцикл не зробить нічого більше, ніж збільшення лічильника count.


12

forЗаява :

Оператор for - це оператор циклу, структура якого забезпечує легку ініціалізацію змінних, тестування виразів та модифікацію змінних. Це дуже зручно для виготовлення контрольованих петель. Ось загальна форма заяви:

[...]

Нульова заява :

Затвердження нуль є лише одна точка з коми.

Нульове твердження нічого не робить. Він ніде не зберігає значення. Це не спричиняє часу, щоб пройти під час виконання вашої програми.

Найчастіше нульовий оператор використовується як тіло оператора циклу або як одне або декілька виразів у операторі for. Ось приклад оператора for, який використовує нульовий оператор як тіло циклу (а також розраховує цілочисельний квадратний корінь з n, для розваги):

Ось ще один приклад, який використовує оператор null як тіло циклу for, а також видає вихідні дані:

Нульовий вираз також іноді використовується для позначення мітки, яка в іншому випадку була б останньою річчю в блоці.


У вашому випадку, ;це Null заяву про forзаяві :

Без цього ifоператор for стає:

Тому поводяться інакше.


1
Приємно цитується з документації. +1
Валі

10

Цикл for існує лише для того, щоб збільшити значення count.


9

a forцикл буде (зазвичай) є тіло,

де тіло укладено в брекети { }

Однак для окремого тіла оператора фігурні дужки не є обов’язковими.

; є порожнім твердженням.

Поєднуючи вищевикладене, стає очевидним, що forцикл виконується, поки не стане умоваfalse .


6

Цикл for в основному перебирає всі числа, які менше або дорівнюють, zahlале перевищують 2, і зберігає його у змінній count. Коли він перебирає всі ці числа, він перевіряє, чи zahlділиться на count. Якщо zahlділиться на count, цикл зупиняється. В іншому випадку цикл зупиняється, коли countдорівнює zahl.

Оператор if після циклу for перевіряє, чи countдорівнює zahl. Якщо це так, то це повинно означати, що цикл пройшов через усі числа, менші zahlі більші за 2. Це означає, що zahlділиться на всі числа, менші за нього самого і більші 2, що робить zahlпростими.


0

Це вказує на твердження, для якого використовується цикл for. Він не може бути порожнім. Принаймні він повинен містити одне твердження. ; - це порожній оператор, для якого зроблена ітерація.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.