EXP45-C. 選択文に対して代入を行わない
次の場合は代入演算子を使用しないこと。このような代入演算子は、プログラマが間違いを犯していることを示唆しており、予期せぬ動作を引き起こす可能性がある。
if
、switch
の制御式 (選択文)while
、do...while
の制御式 (反復文)for
の第 2 オペランド (反復文)?:
の第 1 オペランド (選択文)||
や&&
のオペランド (論理演算子)- コンマ演算子の第 2 オペランド (これらのコンテキストでコンマ式を使用する場合)
?:
の第 2 および第 3 オペランド (選択文) (これらのコンテキストで三項式を使用する場合)
違反コード
次のコード例では、代入式が if
文の最も外側の式になっている。
if (a = b) { /* ... */ }
このコードの意図は、a
に b
を代入して結果の値が 0 と等しいかを判定することである可能性もあるが、プログラマの間違いで等価演算子 ==
の代わりに代入演算子 =
が使用されている場合が非常に多い。そのため、多くのコンパイラがこの条件文を警告する。このコーディングエラーは、「MSC00-C. 高い警告レベルで警告を出さずにコンパイルする」に従うことで検知できる。
適合コード
コードの意図が a
に b
を代入することでないならば、次のように修正すると、a
と b
が等しい場合に条件ブロックが実行される。
if (a == b) { /* ... */ }
実際に代入を意図している場合の適合コードは次のようになる。
if ((a = b) != 0) { /* ... */ }
条件式に代入式が混ざっているため、プログラマの意図にもよるが、一般にこのコードは好ましいとはいえない。とはいえ、プログラマの意図が代入であることは明らかである。
違反コード
次のコード例では、式 x = y
を while
文の制御式として使用している。
do { /* ... */ } while ( foo(), x = y ) ;
適合コード
コードの意図が x
に y
を代入することでないならば、次のように修正すると、x
と y
が等しい場合に条件ブロックが実行される。
do { /* ... */ } while ( foo(), x == y ) ;
実際に代入を意図している場合の適合コードは次のようになる。
do { /* ... */ } while ( foo(), (x = y) != 0) ;
違反コード
次のコード例では、式 p = q
を while
文の制御式として使用している。
do { /* ... */ } while ( x = y, p = q ) ;
適合コード
式 x = y
が while
文の制御式として使用されていないため、これは適合コードである。
do { /* ... */ } while ( x = y, p == q ) ;
例外
EXP45-EX1: 代入の結果自体が比較式または関係式のパラメータである場合、代入を使用することができる。
次のコード例では、式 x = y
自体が比較式のパラメータである。
if ( ( x = y ) != 0 ) { /* ... */ }
EXP45-EX2: 式が 1 つの一次式で構成されている場合、代入を使用することができる。
次のコード例では、式 x = y
は 1 つの一次式である。
if ( ( x = y ) ) { /* ... */ }
EXP45-EX3: 上記のコンテキストでは、関数の引数または配列のインデックスの場合に代入を使用することができる。
次のコード例では、式 x = y
は関数の引数で使用される。
if ( foo( x = y ) ) { /* ... */ }
&&
が比較演算子でも関係演算子でもなく、式全体が一次式でないため、これは違反コードである。
if ( ( v = w ) && flag ) { /* ... */ }
w
への v
の代入が意図されていない場合、この条件ブロックは v
が w
に等しい場合に実行される。
if ( ( v == w ) && flag ) { /* ... */ };
代入を意図している場合には、適合コードは次のようになる。
if ( ( (v = w) != 0 ) && flag ) { /* ... */ };
リスク評価
必要な文字を書き忘れると、意図しないプログラムフローを引き起こすことがある。
ルール |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
EXP45-C |
低 |
高 |
中 |
P6 |
L2 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
Compass/ROSE |
|
|
|
ECLAIR |
1.1 |
exprctxt |
実装済み |
GCC |
V. 4.3.5 |
|
|
V. 9.1 |
ASSIGCOND.GEN |
|
|
LDRA tool suite |
V. 8.5.4 |
9 S |
|
PRQA QA-C | 8.1 | 3314 | 部分的に実装済み |
関連するガイドライン
CERT C++ Secure Coding Standard | EXP19-CPP. Do not perform assignments in conditional expressions |
ISO/IEC TR 24772:2013 | Likely Incorrect Expression [KOA] |
ISO/IEC TS 17961 (ドラフト) | No assignment in conditional expressions [boolasgn] |
MITRE CWE | CWE-480, Use of incorrect operator |
参考資料
[Hatton 1995] | Section 2.7.2, "Errors of Omission and Addition" |
翻訳元
これは以下のページを翻訳したものです。
EXP45-C. Do not perform assignments in selection statements (revision 42)