﻿# V2661\. MISRA\. A 'for' loop should be well\-formed\.

Диагностическое правило основано на руководстве [MISRA](https://misra.org.uk/) \(Motor Industry Software Reliability Association\) по разработке программного обеспечения\.

Правило актуально только для языка C\.

Цикл `for` должен быть отформатирован в соответствии со следующими правилами:

Первый оператор цикла \(`Init-statement`\) должен:

* либо быть пустым; 
* либо не иметь постоянных побочных эффектов;
* либо определять и инициализировать счётчик цикла\.

Второй оператор \(`Condition`\) должен:

* не иметь постоянных побочных эффектов;
* использовать счётчик или его же совместно с флагом управления циклом;
* не использовать объекты, которые модифицируются в теле цикла\.

Третий оператор цикла \(`Expression`\) должен:

* не иметь постоянных побочных эффектов, кроме модификации счетчика цикла;
* не использовать объекты, которые модифицируются в теле цикла\.

Соблюдение правил оформления циклов `for` снижает вероятность ошибок, а также упрощает процесс отладки и обзора кода\. Такой подход позволяет сразу видеть всю логику работы цикла в его заголовке, исключая непредсказуемое поведение\.

**Примечание\.** Допустимо использовать цикл с тремя пустыми операторами `for( ; ; )`\.

Рассмотрим пример некорректного кода:

```cpp
for (size_t i = 0;
     i < users.size() && retry_count < MAX_RETRIES; // <=
     i += (retry_count > 0 ? 0 : 1))                // <=
{
  if (!checkUser(users[i])) 
  {
    retry_count += 1;        // <=
  } 
  else
  {
    retry_count = 0;         // <=
  }
  // ....
}
```

Опасность кода заключается в неочевидном зависании цикла на проблемном пользователе\. Если функция `checkUser` постоянно возвращает `false` при обработке какого\-то пользователя, цикл застревает на одной позиции, пока не исчерпает все попытки\. Это приводит к пропуску всех последующих пользователей, что бывает сложно обнаружить при обзоре кода\.

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

Исправленный код:

```cpp
bool checkUserWithRetry(const std::string& user) {
    for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
        if (checkUser(user)) return true;
    }
    return false;
}
// ....
for (size_t i = 0; i < users.size(); i++) {
    if (!checkUserWithRetry(users[i])) {
        logError("Failed to process user: " + users[i]);
    }
}
// ....
```