メインコンテンツ

MISRA C:2012 Rule 14.1

A loop counter shall not have essentially floating type

説明

ルール定義

A loop counter shall not have essentially floating type 1 .

根拠

浮動小数点ループ カウンターを使用すると、丸め誤差が累積されて、実際の反復回数が期待される回数と異なってくる可能性があります。この丸め誤差は、浮動小数点の基数のべき乗ではないループ ステップを浮動小数点で表現される値に丸める場合に発生します。

浮動小数点ループ カウンターを含むループが、ある実装では正常に動作しているようでも別の実装では異なる反復回数を示す可能性があります。

Polyspace 実装

ループ カウンター変数が実質的な浮動小数点型の場合、Polyspace® はこのルールの違反を報告します。

変数がループ カウンターであるかどうかを判断するために、チェッカーはループの制御式のみを考慮します。特に以下に注意してください。

  • ループを中断するために浮動小数点変数が使用されていても、この変数がループ制御式で使用されていない場合、Polyspace はこの変数をループ カウンターと見なしません。たとえば、以下の例では float 型の変数 loopBreaker はループ カウンターと見なされず、ループを中断するためにこの変数を使用することは、このルールに対する違反になりません。

    float loopBreaker = 0.0f; /* No violation raised */
    while(1) {
        if(loopBreaker > 5.0f)
            break;
        loopBreaker += 1.0f;
    }

  • 変数がループ カウンターであるかどうかを判断する際に、Polyspace は、その変数がループの存続期間中に単調に変化するかどうかや、変数がループの各ステップで変わるかどうかはチェックしません。

トラブルシューティング

ルール違反を想定していてもその違反が表示されない場合、コーディング規約違反が想定どおりに表示されない理由の診断を参照します。

すべて展開する

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;
    }
}

この例では、3 つの for ループで 3 つの異なるループ カウンターが示されています。1 番目と 2 番目の for ループは浮動小数点型変数をループ カウンターとして使用しているため準拠しません。3 番目のループは整数 count をループ カウンターとして使用しています。count がループ内で浮動小数点として使用されていても、ループ インデックスとして動作する場合は変数は整数のままです。したがって、この for ループは準拠しています。

この例は 2 つの while ループを示しています。これらのループは、while ループ条件で浮動小数点変数を使用しています。

  • 1 番目の while ループは、ループ条件とループ内で浮動小数点変数 foo を使用しています。foo がループで更新されると、浮動小数点の丸め誤差が予期しない動作を引き起こす可能性があります。Polyspace は違反を報告します。

  • 2 番目の while ループは、ループ条件で浮動小数点配列 buffer と 2 つの整数 iter1 および inter2 を使用しています。Polyspace は iter1iter2 をループ カウンターとして識別します。これらのループ カウンターは浮動小数点変数ではないので、Polyspace は違反を報告しません。

int main(void){
    unsigned int iter1 =0;
    int iter2;
    float foo;
    double buffer[2];
    double tmp;

    foo = 0.0f;
    while (foo < 1.0f){/* Non-compliant - foo used as a loop counter */
        foo += 0.001f;  
    }
       
	//...
    while((iter1+1 < 2)&& (buffer[iter1]<buffer[iter2])){ //Compliant - loop counter is integer
		// swap buffer[iter1] and buffer[iter2]
        tmp = buffer[iter2];
        buffer[iter2] = buffer[iter1];
        buffer[iter1] = tmp;
        iter2 = iter1;
        iter1++;
    }
						
    return 1; 
}

チェック情報

グループ: 制御ステートメントの式
カテゴリ: 必要
AGC カテゴリ: 推奨

バージョン履歴

すべて展開する


1 All MISRA coding rules and directives are © Copyright The MISRA Consortium Limited 2021.

The MISRA coding standards referenced in the Polyspace Bug Finder™ documentation are from the following MISRA standards:

  • MISRA C:2004

  • MISRA C:2012

  • MISRA C:2023

  • MISRA C++:2008

  • MISRA C++:2023

MISRA and MISRA C are registered trademarks of The MISRA Consortium Limited 2021.