Каков полный синтаксис цикла 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
описание синтаксиса цикла.
Решение
Запятая не исключает циклов 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 Операторы итерации
¶5. Заявление итерации - это блок, сфера которой является строгое подмножество объема его блока.Корпус петли также является блоком, сфера которой является строгое подмножество объема операции итерации.
Это также описано в «Обосновании» с точки зрения дополнительного набора скобок.
Во-вторых, 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 Оператор for
Заявление
for ( clause-1 ; expression-2 ; expression-3 ) statement
ведет себя следующим образом:Экспрессия экспрессии-2-это контролирующая экспрессия, которая оценивается до каждого выполнения тела петли.Экспрессия экспрессии-3 оценивается как пустое экспрессия после каждого выполнения тела петли.Если пункт-1 является объявлением, объем любых переменных, которые он заявляет, является оставшейся частью объявления и всего цикла, включая два других выражения;Это достигается в порядке выполнения до первой оценки контролирующего выражения.Если пункт-1 является выражением, он оценивается как пустое выражение перед первой оценкой контрольной экспрессии.133)
И пункт 1, и выражение 3 можно опустить.Пропущенное выражение-2 заменяется ненулевой постоянной.
133) Таким образом, CLAUE-1 указывает инициализацию для цикла, возможно, объявляя одну или несколько переменных для использования в цикле;Контролирующая экспрессия, экспрессия-2, определяет оценку, проведенную перед каждой итерацией, так что выполнение цикла продолжается до тех пор, пока выражение не сравнится с равным 0;и Expression-3 указывает операцию (такую как увеличение), которая выполняется после каждой итерации.
Другие советы
Запятая просто разделяет два выражения и действует в любом месте C, где допускается нормальное выражение. Они выполняются в порядке слева направо. Значение самого правого выражения - это значение всего выражения.
Циклы for
состоят из трех частей, любая из которых также может быть пустой; один (первый) выполняется в начале, а один (третий) в конце каждой итерации. Эти части обычно инициализируют и увеличивают счетчик соответственно; но они могут делать что угодно.
Вторая часть - это тест , который выполняется в начале каждого выполнения. Если тест выдает false
, цикл прерывается. Вот и все, что нужно сделать.
Цикл for в стиле C состоит из трех выражений:
for (initializer; condition; counter) statement_or_statement_block;
- Инициализатор запускается один раз при запуске цикла.
- Условие проверяется перед каждой итерацией.Цикл выполняется до тех пор, пока его значение истинно.
- Счетчик запускается один раз после каждой итерации.
Каждая из этих частей может быть выражением, допустимым на языке, на котором вы пишете цикл.Это означает, что их можно использовать более творчески.Все, что вы хотите сделать заранее, может войти в инициализатор, все, что вы хотите сделать между ними, может войти в условие или счетчик, вплоть до того момента, когда у цикла больше не будет тела.
Для этого очень удобен оператор запятая.Это позволяет вам объединять выражения в одну цепочку, чтобы сформировать одно новое выражение.Большую часть времени он используется таким образом в цикле for, другие значения оператора запятой (например.соображения присвоения ценности) играют второстепенную роль.
Несмотря на то, что вы можете делать умные вещи, творчески используя синтаксис, я бы воздерживался от этого, пока не найду подходящее решение. Действительно веская причина сделать это.Игра в гольф с циклами for делает код труднее читать, понимать (и поддерживать).
В Википедии есть хорошая статья о цикле for также.
В цикле for
все необязательно. Мы можем инициализировать более одной переменной, мы можем проверить более одного условия, мы можем перебрать более одной переменной, используя оператор запятой.
Следующий цикл for
приведет вас к бесконечному циклу. Будьте осторожны, проверяя состояние.
for(;;)
Конрад упомянул ключевой момент, который я хотел бы повторить: значение самого правого выражения - это значение всего выражения.
Компилятор Gnu объявил об этом предупреждении, когда я поместил два теста в "условие" раздел цикла for
warning: left-hand operand of comma expression has no effect
Что я на самом деле намеревался для "условия"? было два теста с & amp; & amp; " между. Согласно утверждению Конрада, только условие справа от запятой может повлиять на состояние.
цикл for выполняется в течение определенного времени for(;;)
синтаксис цикла for
для(;;)
ИЛИ
для (инициализатор;состояние;прилавок)
например (rmv=1;rmv<=15;rmv++)
выполнение до 15 раз за блок
1. сначала инициализируйте значение, потому что запустите значение
(например)rmv=1 или rmv=2
2.Второй оператор проверяет, условие истинно или ложно, условие истинно, время выполнения цикла for и условие ложно, завершает блок,
например, i=5;i<=10, условие истинно
i=10;i<10 the condition is false terminate for block,
3.третий — увеличение или уменьшение
(например)rmv++ или ++rmv