PRE07-C. "??" の繰り返しは避ける
"?" 2つは3文字表記の始まりを表す。C 言語規格のセクション 5.2.1.1 には次のように記載されている[ISO/IEC 9899:2011]。
次に示す文字の並び[3文字表記(trigraph sequenceという。)]がソースファイルの中にある場合、その三つの文字の並びを対応する一文字に置き換える。
??=
#
??)
]
??!
|
??(
[
??'
^
??>
}
??/
\
??<
{
??-
~
違反コード
このコード例では、a++
が実行されない。なぜなら、3文字表記 ??/
が \
に置き換えられ、a++
がコメント行と同一行に配置されてしまうからである。
// a の値はなんだろう??/ a++;
適合コード
以下のコード例は、"?" の間に空白文字をひとつ入れることにより、予期せず3文字表記にならないようにしている。
// a の値はなんだろう? ?/ a++;
違反コード
このコード例は3文字表記 ??!
を含む。これは |
に置き換えられる。
size_t i = /* 初期値 */; if (i > 9000) { if (puts("Over 9000!??!") == EOF) { /* エラー処理 */ } }
C言語規格に適合したコンパイラを使うと、このコードの出力は Over 9000!|
になる。
適合コード
以下の適合コードでは、文字列連結を用いて二つの "?" を連結している。このようにしなければ 3 文字表記の始まりと解釈されてしまう。
size_t i = /* 初期値 */; /* i への代入 */ if (i > 9000) { if (puts("Over 9000!?""?!") == EOF) { /* エラー処理 */ } }
このコードは意図したとおり Over 9000!??!
を出力する。
リスク評価
うっかり3文字表記をしてしまうと予期せぬ動作を引き起こすおそれがある。コンパイラによっては、3文字表記がある場合に警告を出すオプションや3文字表記を無効にするオプションを提供している。警告を出すオプションを使用し、コンパイル時に警告が出ないようなコードにせよ。(「MSC00-C. 高い警告レベルでのコンパイルで警告が出ないようにする」を参照。)
レコメンデーション |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
PRE07-C |
低 |
低 |
中 |
P2 |
L3 |
自動検出(最新の情報はこちら)
ツール | バージョン | チェッカー | 説明 |
---|---|---|---|
ECLAIR |
1.1 |
dtrigraf |
実装済み |
GCC | V. 4.3.5 |
|
|
LDRA tool suite |
V. 8.5.4 |
81 S |
実装済み |
PRQA QA-C | 8.1 | 3601 | 部分的に実装済み |
関連するガイドライン
CERT C++ Secure Coding Standard | PRE07-CPP. Avoid using repeated question marks |
MISRA-C | Rule 4.2 |
参考資料
[ISO/IEC 9899:2011] | Section 5.2.1.1, "Trigraph Sequences" |
翻訳元
これは以下のページを翻訳したものです。
PRE07-C. Avoid using repeated question marks (revision 80)