Правило 14.2 MISRA C:2012

Цикл for должен быть правильно построен

Описание

Управляйте определением

Цикл for должен быть правильно построен.

Объяснение

Оператор for предоставляет услугу цикличного выполнения общего назначения. Используя ограниченную форму цикла делает код легче рассмотреть и анализировать.

Реализация Polyspace

Polyspace® проверяет что:

  • Индекс цикла for (V) является переменным символом.

  • V является последней присвоенной переменной в первом выражении (если есть).

  • Если первое выражение существует, оно содержит присвоение V.

  • Если второе выражение существует, это - сравнение V.

  • Если третье выражение существует, это - присвоение V.

  • Нет никаких прямых присвоений индекса цикла for.

Обменивайтесь сообщениями в отчете

  • 1-е выражение должно быть присвоением. Следующие виды циклов for позволены:

    • должны присутствовать все три выражения;

    • 2-е и 3-и выражения должны присутствовать с предшествующей инициализацией счетчика цикла;

    • все три выражения должны быть пустыми для преднамеренного бесконечного цикла.

  • 3-е выражение должно быть присвоением счетчика цикла.

  • 3-е выражение: присвоенная переменная должна быть счетчиком цикла (counter).

  • 3-е выражение должно быть присвоением счетчика цикла (counter) только.

  • 2-е выражение должно содержать сравнение со счетчиком цикла (counter).

  • Счетчик цикла (counter) не должен быть изменен в теле цикла.

  • Плохо введите счетчик цикла for (counter).

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

развернуть все

void foo(void){

    for(short index=0; index < 5; index++){  /* Non-compliant */
        index = index + 3;       /* Altering the loop counter */
    }
}

В этом примере счетчик цикла index изменяется в цикле for. Трудно определить, когда цикл останавливается.

Исправление — использует другую переменную, чтобы остановиться рано

Одно возможное исправление должно использовать дополнительный флаг, чтобы отключить цикл рано.

В этом исправлении второй пункт цикла for зависит от встречного значения, index < 5, и на дополнительный флаг, !flag. С дополнительным флагом определение цикла for и счетчик остаются читаемыми, и можно выйти из цикла рано.

#define FALSE 0
#define TRUE  1

void foo(void){

    int flag = FALSE;

    for(short index=0; (index < 5) && !flag; index++){ /* Compliant */
        if((index % 4) == 0){
            flag = TRUE;        /* allows early termination of loop */
        }
    }
}
void foo(void)
    for(short index = 0; ; index++) {}   /* Non-compliant */

    for(short index = 0; index < 10;) {} /* Non-compliant */

    short index;
    for(; index < 10;) {}     /* Non-compliant */

    for(; index < 10; i++) {} /* Compliant */

    for(;;){}  
          /* Compliant - Exception all three clauses can be empty */
}

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

Одним исключением является цикл for со всеми тремя пустыми пунктами, чтобы допускать бесконечные циклы.

Проверяйте информацию

Группа: управляйте выражениями оператора
Категория: необходимый
Категория AGC: удобочитаемость
Язык: C90, C99