Подтвердить что ты не робот

Каков полный синтаксис цикла 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.

4b9b3361

Ответ 1

Запятая не предназначена для циклов; это оператор запятой.

x = (a, b);

будет делать сначала a, затем b, а затем установить x в значение b.

Синтаксис for:

for (init; condition; increment)
    ...

Это несколько (без учета continue и break), эквивалентных:

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

Итак, ваш пример цикла (снова игнорируя 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 или что-то еще не прерывает цикл).
  • A 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

ведет себя следующим образом: выражение expression-2 является управляющим выражением, которое оценивается перед каждым исполнением тела цикла. Выражение выражение-3 оценивается как выражение void после каждого выполнения тела цикла. Если предложение-1 является объявление, объем любых переменных, которые он объявляет, является остатком декларации и весь цикл, включая два других выражения; это достигается в порядке исполнения перед первой оценкой контролирующего выражения. Если выражение-1 является выражением, оно оценивается как выражение void перед первой оценкой контролирующего выражения. 133)

Оба предложения-1 и выражение-3 могут быть опущены. Пропущенное выражение-2 заменяется на ненулевая константа.

133) Таким образом, предложение-1 указывает инициализацию цикла, возможно, объявляя одну или несколько переменных для использования в петля; управляющее выражение, выражение-2, определяет оценку, сделанную перед каждой итерацией, так что выполнение цикла продолжается до тех пор, пока выражение не сравнится с 0; и выражение-3 определяет операцию (например, приращение), которая выполняется после каждой итерации.

Ответ 2

С++ позволяет перегружать запятую. Серьезно.

Ответ 3

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

Циклы

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

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

Ответ 4

Стиль C для цикла состоит из трех выражений:

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

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

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

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

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

Ответ 5

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

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

for(;;) 

Ответ 6

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

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

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

То, что я действительно предназначалось для "условия", было два теста с "& &" между. Per Konrad, только тест справа от запятой повлияет на условие.

Ответ 7

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

syntex для цикла

для (;;)

ИЛИ

для (initializer; condition; counter)

e.g(rmv = 1; rmv = 15; rmv ++)

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

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

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

Операция 2.second - это тест, это условие истинно или ложно, условие true no.of времени выполнения цикла for и условие false завершается для блока,

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

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

3. Третье - это приращение или уменьшение

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