この記事は、インテル® デベロッパー・ゾーンに公開されている「The Ultimate Question of Programming, Refactoring, and Everything」の日本語参考訳です。
9. 終端 null 文字には ‘\0’ を使用する
Notepad++ プロジェクトから抜粋した以下のコードについて考えてみます。このエラーは、次の PVS-Studio 診断によって検出されます。
V528 It is odd that pointer to ‘char’ type is compared with the ‘\0’ value. Probably meant: *headerM != ‘\0’. (V528 ‘char’ 型へのポインターが ‘\0’ 値と比較されています。*headerM != ‘\0’ の間違いだと考えられます。)
TCHAR headerM[headerSize] = TEXT(""); ... size_t Printer::doPrint(bool justDoIt) { ... if (headerM != '\0') ... }
説明
この例では、終端 null (英語) 文字に ‘\0’ が使用されているため、エラーを簡単に見つけて修正できます。しかし、もしコードが次のように記述されていたらどうでしょうか?
if (headerM != 0)
配列アドレスは 0 と比較され、結果は常に true になります。この場合、エラーなのか、冗長なチェックなのか判断しかねます。特に、別のプログラマーが記述したコードやずっと前に記述されたコードではなおさらです。
この例では、’\0′ が使用されているため、プログラマーは 1 文字の値をチェックしたいのだと推測できます。また、headerM ポインターと NULL の比較は意味がないことも分かっています。これらすべてを考慮して、文字列が空かどうかチェックしようとして、プログラマーが間違ったコードを記述したことを推測できます。このコードを修正するには、ポインターの逆参照を追加する必要があります。
正しいコード
TCHAR headerM[headerSize] = TEXT(""); ... size_t Printer::doPrint(bool justDoIt) { ... if (*headerM != _T('\0')) ... }
推奨事項
0 は、NULL、false、null 文字 ‘\0’、または数値 0 を指す可能性があります。そのため、面倒がらずに、常に短縮形の 0 は使用しないようにします。短縮形の 0 は、コードを分かりづらくし、エラーを見つけにくくします。
次の表記を使用します。
- 0 – 整数のゼロに使用
- nullptr – null ポインタ―に使用 (C++)
- NULL – null ポインターに使用 (C)
- ‘\0’、L’\0’、_T(‘\0’) – 終端 null に使用
- 0.0、0.0f – 浮動小数点型のゼロに使用
- false、FALSE – ‘false’ 値に使用
この規則に従うことで、コードが分かりやすくなり、コードレビュー時に不具合を見つけやすくなります。
コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。