STR10-C. 型が異なる文字列リテラルを結合しない
MISRA 2008 では、ワイド文字列リテラルとナロー文字列リテラルの結合は、未定義の動作を引き起こすとされている。これは、C90 [ISO/IEC 9899:1990] までは未定義の動作であると考えられていた。しかし、この動作は C99 において定義された動作となり [ISO/IEC 9899:1999]、C11 のセクション 6.4.5、第 5 段落には次のように説明が追加されている [ISO/IEC 9899:2011]。
翻訳フェーズ6において、隣り合う単純文字列リテラル字句または、同一の接頭語を持つ文字列リテラル字句で指定される多バイト文字の並びは、連結して一つの多バイト文字の並びになる。字句のいずれかが文字エンコーディングの接頭語を持つ場合、結果として生じる多バイト文字の並びは、同じ接頭語を持つものとして扱う。それ以外の場合、それは単純文字列リテラルとして扱う。接頭語の異なるワイド文字列リテラル字句を連結できるかどうか、また、それが可能な場合、結果としてして生じるマルチバイト文字の並びの取扱いについては、処理系定義とする。
このように規定されてはいるものの、連結する文字列リテラルは、すべて同じ型を持つことが望ましい。そうすることで、処理系定義の動作に依存せず、またC90のみをサポートするプラットフォームにおいてコンパイルされた場合に、未定義の動作になることを防ぐことができる。
違反コード (C90)
以下のコード例では、ワイド文字列リテラルとナロー文字列リテラルを結合している。C90において、このプログラムの動作は未定義であるが、プログラマの意図はおそらく、ワイド文字列リテラルを作成することである。
wchar_t *msg = L"This message is very long, so I want to divide it " "into two parts.";
適合コード (C90, ワイド文字列リテラル)
結合した文字列をワイド文字列リテラルにする必要がある場合は、次の適合コードに示すように、結合する各文字列はワイド文字列リテラルでなければならない。
wchar_t *msg = L"This message is very long, so I want to divide it " L"into two parts.";
適合コード (C90, ナロー文字列リテラル)
ワイド文字列リテラルである必要がない場合は、次の適合コードに示すように、ナロー文字列リテラルを使用する方がよい。
char *msg = "This message is very long, so I want to divide it " "into two parts.";
リスク評価
ワイド文字列リテラルとナロー文字列リテラルを結合すると、未定義の動作を引き起こす可能性がある。
ルール |
深刻度 |
可能性 |
修正コスト |
優先度 |
レベル |
---|---|---|---|---|---|
STR10-C |
低 |
中 |
中 |
P4 |
L3 |
自動検出(最新の情報はこちら)
ツール |
バージョン |
チェッカー |
説明 |
---|---|---|---|
ECLAIR | 1.1 |
stltccat |
実装済み |
関連するガイドライン
MISRA-C++ | Rule 2-13-5 |
参考資料
[ISO/IEC 9899:2011] | Section 6.4.5, "String Literals" |
翻訳元
これは以下のページを翻訳したものです。
STR10-C. Do not concatenate different type of string literals (revision 30)