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)



