Каков полный синтаксис цикла for в C?

Я видел несколько очень странных циклов for при чтении чужого кода. Я пытался найти полное синтаксическое объяснение цикла for на языке C, но это очень сложно, потому что слово «for» встречается в несвязанных предложениях, что делает поиск практически невозможным для Google.

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

for здесь:

for(p=0;p+=(a&1)*b,a!=1;a>>=1,b<<=1);

В среднем условии есть запятая, разделяющая два фрагмента кода, что делает эта запятая? Я понимаю, что запятая справа делает и a>>=1, и b<<=1.

Но что происходит в условиях выхода из цикла? Выходит ли при p==0, при a==1 или при обоих случаях?

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

@Jesus - Вы исправили "kinda" на "kind of", "coma" to "comma", написали "I" и "Does" с заглавной буквы, но оставили "ppl" для людей?

James Caccese 24.03.2009 23:25

Исправлены некоторые ошибки. Пост теперь выглядит намного лучше. Интересный вопрос.

George Stocker 30.03.2009 19:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
59
2
95 443
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Запятая просто разделяет два выражения и действительна в любом месте C, где разрешено нормальное выражение. Они выполняются слева направо. Значение самого правого выражения - это значение всего выражения.

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

Вторая часть - это тестовое задание, которая выполняется в начале каждого выполнения. Если тест дает false, цикл прерывается. Это все, что нужно сделать.

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

quikchange 17.04.2009 03:31
Ответ принят как подходящий

Запятая не исключает циклы for; это оператор запятой.

x = (a, b);

сначала выполнит a, затем b, а затем установит x в значение b.

Синтаксис for:

for (init; condition; increment)
    ...

Что в некоторой степени (без учета continue и break) эквивалентно:

init;
while (condition) {
    ...
    increment;
}

Итак, ваш пример цикла for (снова игнорируя continue и break) эквивалентен

p=0;
while (p+=(a&1)*b,a!=1) {
    ...
    a>>=1,b<<=1;
}

Что действует так, как если бы это было (снова игнорируя continue и break):

p=0; 
while (true) {
    p+=(a&1)*b;
    if (a == 1) break;
    ...
    a>>=1;
    b<<=1;
}

Две дополнительные детали цикла for, которых не было в упрощенном преобразовании в цикл while выше:

  • Если условие опущено, это всегда true (что приводит к бесконечному циклу, если только break, goto или что-то еще не прерывает цикл).
  • continue действует так, как если бы это был переход к метке непосредственно перед приращением, в отличие от continue в цикле while, который пропускал бы приращение.

Кроме того, важная деталь об операторе запятой: это точка последовательности, такая как && и || (поэтому я могу разделить ее на отдельные операторы и сохранить ее значение в неизменном виде).


Изменения в C99

Стандарт C99 вводит несколько нюансов, не упомянутых ранее в этом объяснении (что очень хорошо для C89 / C90).

Во-первых, все петли сами по себе являются блоками. Фактически,

for (...) { ... }

сам завернут в скобки

{
for (...) { ... }
}

Стандарт гласит:

ISO/IEC 9899:1999 §6.8.5 Iteration statements

¶5 An iteration statement is a block whose scope is a strict subset of the scope of its enclosing block. The loop body is also a block whose scope is a strict subset of the scope of the iteration statement.

Это также описано в Обосновании с точки зрения дополнительного набора скоб.

Во-вторых, часть init в C99 может быть (одиночным) объявлением, как в

for (int i = 0; i < sizeof(something); i++) { ... }

Теперь «блок, обернутый вокруг цикла» вступает в свои права; это объясняет, почему переменная i не может быть доступна вне цикла. Вы можете объявить несколько переменных, но все они должны быть одного типа:

for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }

Стандарт гласит:

ISO/IEC 9899:1999 §6.8.5.3 The for statement

The statement

for ( clause-1 ; expression-2 ; expression-3 ) statement

behaves as follows: The expression expression-2 is the controlling expression that is evaluated before each execution of the loop body. The expression expression-3 is evaluated as a void expression after each execution of the loop body. If clause-1 is a declaration, the scope of any variables it declares is the remainder of the declaration and the entire loop, including the other two expressions; it is reached in the order of execution before the first evaluation of the controlling expression. If clause-1 is an expression, it is evaluated as a void expression before the first evaluation of the controlling expression.133)

Both clause-1 and expression-3 can be omitted. An omitted expression-2 is replaced by a nonzero constant.

133) Thus, clause-1 specifies initialization for the loop, possibly declaring one or more variables for use in the loop; the controlling expression, expression-2, specifies an evaluation made before each iteration, such that execution of the loop continues until the expression compares equal to 0; and expression-3 specifies an operation (such as incrementing) that is performed after each iteration.

В языке C запятая имеет более низкий приоритет, чем присвоение, поэтому «x = a, b;» сначала установит x в a, затем сделает b.

ephemient 03.12.2008 23:05

@DavidThornley, что, если бы это было x = a, b; а не (а, б)?

TM. 25.03.2009 01:14

@TM: если я правильно понял, «x = a, b» присвоит a переменной x, затем вычислит b и отбросит его значение.

onnodb 30.03.2009 12:58

Цикл for в стиле C состоит из трех выражений:

for (initializer; condition; counter) statement_or_statement_block;
  • Инициализатор запускается один раз при запуске цикла.
  • Условие проверяется перед каждой итерацией. Цикл выполняется до тех пор, пока его значение истинно.
  • Счетчик запускается один раз после каждой итерации.

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

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

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

В википедии тоже есть хороший статья о цикле for.

Разрешен ли еще один цикл for в разделе counter, который позволит определять вложенные циклы for в том же операторе? Другими словами, как составной цикл for определяется в C / C++?

lifebalance 07.09.2014 19:21

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

Tomalak 07.09.2014 19:25

И я последовал твоему совету, вот отвечать. И, пожалуйста, проголосуйте за вопрос, если вы так считаете. Наслаждаться!

lifebalance 07.09.2014 22:25

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

Следующий цикл for перенесет вас в бесконечный цикл. Будьте осторожны, проверяя состояние.

for(;;) 

Просто впервые увидел это в старом коде C 90-х годов, выходя с "goto", серьезно ??

B M 01.10.2017 21:19

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

Компилятор Gnu сообщил об этом предупреждении, когда я поместил два теста в раздел «условие» цикла for.

warning: left-hand operand of comma expression has no effect

На самом деле я имел в виду два теста с символом «&&» между ними. По утверждению Конрада, только тест справа от запятой повлияет на состояние.

что вы имеете в виду под «значением крайнего правого выражения - значением overall expression.»? Я полагаю, вы имеете в виду: «Значение крайнего правого выражения - это значение всего comma expression»?

Allan Ruin 27.05.2012 13:11

цикл for выполняется в течение определенного времени для (;;)

синтекс для цикла

для(;;)

ИЛИ ЖЕ

for (инициализатор; условие; счетчик)

например (rmv = 1; rmv <= 15; rmv ++)

выполнение до 15 раз за блок

1. сначала инициализируйте значение, потому что начните значение

(например) rmv = 1 или rmv = 2

2. второй оператор проверяет, является ли условие истинным или ложным, истинным условием является количество времени выполнения цикла for и условие ложно завершение для блока,

например, я = 5; я <= 10 условие истинно

i=10;i<10 the condition is false terminate for block,

3. третья - увеличение или уменьшение

(например) rmv ++ или ++ rmv

У вас ужасное форматирование. Вы должны писать код в моноширинном формате. Чтобы создать блок кода, сделайте отступ для каждой принадлежащей ему строки, используя 4 пробела. Чтобы сделать такой inline monospace, используйте `в начале и в конце текста, который вы хотите моноширинный.

GingerPlusPlus 14.10.2014 17:28

Кроме того, for(;;) не является альтернативным синтаксисом; это нормальный синтаксис с пропущенными инициализатором, условием и счетчиком.

GingerPlusPlus 14.10.2014 17:30

Другие вопросы по теме