MISRA C 2004ガイドラインを含むコード標準を持つ安全性が重要なドメインの場合、主にすべてのif()
ステートメントにelse
そして、関数ごとに1つの戻り値、およびループごとに1つのブレークがあることを示します。元のコードは次のようになりました。
while (bIncrementalOperation(&data))
{
vCode;
if (bCondition1)
{
u16Status |= u16STATUS_N1;
break;
}
if (bCondition2)
{
u8Var++;
}
if (bCondition3)
{
u16Status |= u16STATUS_N2;
break;
}
if (bCondition4)
{
break;
}
if (bCondition5)
{
vCode;
}
else
{
if (bCondition6)
{
break;
}
}
vCode;
}
これはフォーマットのために長いですが、かなり簡潔です。比較すると、コンプライアンスを試みる場合、次のようになります。
bContinue = TRUE;
while (bContinue)
{
bContinue = bIncrementalOperation(&data);
if (!bContinue)
{
/* Normal exit condition: ... */
}
else
{
bContinue = bCondition1;
if (!bContinue)
{
u16Status |= u16STATUS_N1;
}
else
{
u8Var += (bCondition2) ? 1U : 0U;
bContinue = (bCondition3);
if (!bContinue)
{
u16Status |= u16STATUS_N2;
}
else
{
bContinue = bCondition4;
if (!bContinue)
{
/* Normal exit condition: .... */
}
else
{
if (bCondition5)
{
vCode;
}
else if (bCondition6)
{
/* Normal exit condition: ... */
break;
}
else
{
/* Continue to do IncrementalOperation */
}
vCode;
}
}
}
}
}
このパターンは頻繁に発生します。特に、複数の障害モードに対してテストを行う保護機能で発生し、バグが発生します。 MISRA要件に違反しない、より良いパターンはありますか?
MISRA C:2012には必須ルール14.9が含まれていません:「if(expression)構造の後には複合ステートメントが必要です。」または必須の規則14.10:「すべてのif/elseifは、 'else'句で終了する必要があります。」
問題が解決しました。
ルール15.5:「関数は最後に単一の出口点を持つ必要があります」は勧告ではなく必須です。単一の出口点の主な動機は手動のメモリ管理を正しく行うのを容易にするため。関数がメモリを割り当てない場合、おそらくそれは必要ありません。
MISRA C:2004 Rule 14.10を誤って読んでいることに注意してください。 else if
ステートメントにのみ適用されます。
このルールは、
if
ステートメントの後に1つ以上のelse if
ステートメントが続く場合に常に適用されます。最後のelse if
の後にはelse
ステートメントが続きます。 単純なif
ステートメントの場合、else
ステートメントを含める必要はありません。最後の
else
ステートメントの要件は、防御的プログラミングです。else
ステートメントは、適切なアクションを実行するか、アクションを実行しない理由に関する適切なコメントを含む必要があります。これは、default
ステートメントに最後のswitch
句を含めるという要件と一致しています。
MISRA C:2004ルール14.9は、「if
ステートメントでは常に中括弧を使用する」と読むことができます。