MISRA C:2012 Rule 14.1

A loop counter shall not have essentially floating type

Description

Rule Definition

A loop counter shall not have essentially floating type.

Rationale

When using a floating-point loop counter, accumulation of rounding errors can result in a mismatch between the expected and actual number of iterations. This rounding error can happen when a loop step that is not a power of the floating point radix is rounded to a value that can be represented by a float.

Even if a loop with a floating-point loop counter appears to behave correctly on one implementation, it can give a different number of iteration on another implementation.

Polyspace Implementation

If the for index is a variable symbol, Polyspace® checks that it is not a float.

Troubleshooting

If you expect a rule violation but do not see it, refer to the documentation of Polyspace Code Prover™ or Polyspace Code Prover Server™.

Examples

expand all

int main(void){
    unsigned int counter = 0u;
    int result = 0;
    float foo;

    // Float loop counters
    for(float foo = 0.0f; foo < 1.0f; foo +=0.001f){/* Non-compliant*/
        ++counter;
    }

    float fff = 0.0f; 
    for(fff = 0.0f; fff <12.0f; fff += 1.0f){/* Non-compliant*/
        result++;
    }

    // Integer loop count
    for(unsigned int count = 0u; count < 1000u; ++count){/* Compliant */
        foo = (float) count * 0.001f;
    }
}

In this example, the three for loops show three different loop counters. The first and second for loops use float variables as loop counters, and therefore are not compliant. The third loop uses the integer count as the loop counter. Even though count is used as a float inside the loop, the variable remains an integer when acting as the loop index. Therefore, this for loop is compliant.

int main(void){
    unsigned int u32a;
    float foo;

    foo = 0.0f;
    while (foo < 1.0f){/* Non-compliant - foo used as a loop counter */
        foo += 0.001f;  
    }

    foo = read_float32();
    do{
        u32a = read_u32();
    }while( ((float)u32a - foo) > 10.0f );   
                        /* Compliant - foo doesn't change in the loop */
                        /*  so cannot be a counter */
    return 1; 
}

This example shows two while loops both of which use foo in the while-loop conditions.

The first while loop uses foo in the condition and inside the loop. Because foo changes, floating-point rounding errors can cause unexpected behavior.

The second while loop does not use foo inside the loop, but does use foo inside the while-condition. So foo is not the loop counter. The integer u32a is the loop counter because it changes inside the loop and is part of the while condition. Because u32a is an integer, the rounding error issue is not a concern, making this while loop compliant.

Check Information

Group: Control Statement Expressions
Category: Required
AGC Category: Advisory