MISRA C:2012 Rule 14.2

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

Описание

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

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

Объяснение

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

Реализация Polyspace

Цикл for состоит из оператора управления с тремя пунктами и телом цикла. Средство проверки повышает нарушение если:

  • Первый пункт не содержит инициализацию (за исключением того, когда пункт пуст). Средство проверки рассматривает последнюю присвоенную переменную первого for- пункт цикла как счетчик цикла. Если первый пункт пуст, средство проверки считает переменную постепенно увеличенной или постепенно уменьшенной в третьем пункте как счетчик цикла.

  • Второй пункт не содержит операцию сравнения, включающую счетчик цикла.

  • Третий пункт содержит операцию кроме постепенного увеличения или постепенного уменьшения счетчика цикла (разделенный запятой от шага или декремента).

  • Счетчик цикла имеет тип данных, который не является целым числом или типом указателя.

  • Счетчик цикла постепенно увеличивается в теле цикла.

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

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

Примеры

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

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; index++) {} /* Compliant */

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

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

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

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

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