Запятая не эксклюзивна из для циклов; это - оператор запятой.
x = (a, b);
сделает первый a, тогда b, затем установит x на значение b.
для синтаксиса:
for (init; condition; increment)
...
, Который является несколько (игнорирующий continue
и break
на данный момент) эквивалентен:
init;
while (condition) {
...
increment;
}
, Таким образом, Ваш для примера цикла (снова игнорирование continue
и break
) эквивалентен [1 136]
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;
}
Две дополнительных детали для цикла, которые не были в упрощенном преобразовании в некоторое время цикл выше:
true
(приводящий к бесконечному циклу, если break
, goto
, или что-то еще не повреждает цикл). continue
действия, как будто это был goto к маркировке незадолго до инкремента, в отличие от этого, continue
в цикле с условием продолжения, который пропустит инкремент. кроме того, важная деталь об операторе запятой: это - точка последовательности, как [1 121] и ||
(который является, почему я могу разделить его в отдельных операторах и сохранить его значение в целости).
стандарт C99 представляет несколько нюансов, не упомянутых ранее в этом объяснении (который очень хорош для C89/C90).
Первый, все циклы являются блоками самостоятельно. Эффективно,
for (...) { ... }
самостоятельно обертывается в пару фигурных скобок
{
for (...) { ... }
}
стандарт sayeth:
Операторы цикла ISO/IEC 9899:1999 В§6.8.5
В¶5 оператор цикла является блоком, объемом которого является строгое подмножество объема его блока включения. Тело цикла является также блоком, объемом которого является строгое подмножество объема оператора цикла.
Это также описано в Объяснении с точки зрения дополнительного набора фигурных скобок.
, Во-вторых, init
часть в C99 может быть (единственным) объявлением, как в [1 146]
for (int i = 0; i < sizeof(something); i++) { ... }
Теперь, 'блок повторился, цикл' добивается признания; это объясняет, почему к переменной i
нельзя получить доступ вне цикла. Можно объявить больше чем одну переменную, но они должны все иметь тот же тип:
for (int i = 0, j = sizeof(something); i < j; i++, j--) { ... }
стандарт sayeth:
ISO/IEC 9899:1999 В§6.8.5.3 для оператора
оператор
for ( clause-1 ; expression-2 ; expression-3 ) statement
ведет себя следующим образом: выражение 2 выражения является выражением управления, которое оценено перед каждым выполнением тела цикла. Выражение 3 выражения оценено как пустое выражение после каждого выполнения тела цикла. Выражение if 1 является объявлением, объемом любых переменных, которые это объявляет, является остаток от объявления и всего цикла, включая другие два выражения; это достигнуто в порядке выполнения перед первой оценкой выражения управления. Выражение if 1 является выражением, оно оценено как пустое выражение перед первой оценкой выражения управления. <глоток> 133) глоток>
И пункт 1 и выражение 3 могут быть опущены. Опущенное выражение 2 заменяется ненулевой константой.
<глоток> 133) глоток> Таким образом, пункт 1 определяет инициализацию для цикла, возможно объявляя одну или несколько переменных для использования в цикле; выражение управления, выражение 2, определяет оценку, сделанную перед каждым повторением, таким, что выполнение цикла продолжается, пока выражение не выдерживает сравнение равный 0; и выражение 3 определяет операцию (такую как постепенное увеличение), который выполняется после каждого повторения.
Запятая просто разделяет два выражения и допустима где угодно в C, где нормальное выражение позволяется. Они выполняются в порядке слева направо. Значение самого правого выражения является значением полного выражения.
for
циклы состоят из трех частей, любая из которых может также быть пустой; один (первое) выполняется вначале, и одно (третье) в конце каждого повторения. Эти части обычно инициализируют и увеличивают счетчик, соответственно; но они могут сделать что-либо.
вторая часть тест , который выполняется в начале каждого выполнения. Если тест уступает false
, цикл прерывается. Вот и все.
Стиль C для цикла состоит из трех выражений:
for (initializer; condition; counter) statement_or_statement_block;
Каждая из этих частей может быть выражением, допустимым на языке, в котором Вы пишете цикл. Это означает, что они могут использоваться более творчески. Что-либо, что Вы хотите сделать заранее, может войти в инициализатор, что-либо, что Вы хотите сделать промежуточный, может войти в условие или счетчик, до точки, где цикл больше не имеет никакого тела.
Для достижения этого оператор запятой входит очень удобный. Это позволяет Вам цепочечным выражениям вместе формировать единственное новое выражение. Большую часть времени это используется тот путь в для цикла, другие последствия оператора запятой (например, соображения присвоения значения) играют второстепенную роль.
Даже при том, что можно сделать умные вещи при помощи синтаксиса творчески - я избежал бы его, пока я не нахожу действительно серьезное основание сделать так. Играть в гольф кода с для циклов делает код тяжелее, чтобы считать и понять (и поддержать).
Википедия имеет хорошее статья о для цикла также.
Все является дополнительным в for
цикл. Мы можем инициализировать больше чем одну переменную, мы можем проверить больше чем на одно условие, мы можем выполнить итерации больше чем одной переменной с помощью оператора запятой.
следующий for
цикл возьмет Вас в бесконечный цикл. Будьте осторожны путем проверки условия.
for(;;)
Конрад упомянул ключевой момент, который я хотел бы повторить: значение самого правого выражения - это значение всего выражения.
Компилятор Gnu сообщил об этом предупреждении, когда я поместил два теста в раздел «условие» цикла for
warning: left-hand operand of comma expression has no effect
На самом деле я имел в виду два теста с символом «&&» между ними. По утверждению Конрада, только тест справа от запятой повлияет на состояние.