==
文字列リテラルを演算子(または)を使用して別の文字列リテラルと比較すると!=
、結果は明確に定義されていますか?
たとえば、次のことが保証されていますか?
assert("a" == "a");
assert("a" != "b");
代わりに「usestd::string」のようなものは言わないでください。この特定のケースを知りたいだけです。
==
文字列リテラルを演算子(または)を使用して別の文字列リテラルと比較すると!=
、結果は明確に定義されていますか?
たとえば、次のことが保証されていますか?
assert("a" == "a");
assert("a" != "b");
代わりに「usestd::string」のようなものは言わないでください。この特定のケースを知りたいだけです。
"a" == "a"
この式は、true
またはを生成する可能性がありfalse
ます。保証はありません。2 つの"a"
文字列リテラルは、同じストレージを占有する場合もあれば、メモリ内の 2 つの異なる場所に存在する場合もあります。
C++ 標準で最も近い言語は次のとおりだと思います。その他の要件や制限はないため、結果は指定されていません。
"a" != "b"
false
これら 2 つの文字列リテラルがメモリ内の同じ場所を占有することはできないため、 この式は生成する必要があります: "a"[0] != "b"[0]
.
この方法で文字列リテラルを比較すると、実際にはポインターを配列の最初の要素と比較していることになります。
ポインターを比較しているため、リレーショナル比較 ( <
、>
、<=
、および) は等値比較 (および)>=
よりもさらに問題があります。2 つのポインターが同じ配列へのポインターであるか、同じオブジェクトへのポインターである場合にのみ、2 つのポインターを比較できます。==
!=
2 つの"a"
文字列リテラルがメモリ内の同じ場所を占有している場合、両方のポインターが同じ配列の最初の要素 ( ) を指しているため、"a" < "a"
は適切に定義され、yieldになります。false
'a'
ただし、2 つの"a"
文字列リテラルがメモリ内の異なる"a" < "a"
場所を占有している場合、比較される 2 つのポインターはまったく関連のないオブジェクトを指しているため、 の結果は未定義です。
"a"
and"b"
はメモリ内の同じ場所を占有することはできないため、"a" < "b"
常に未定義の動作をします。他の関係比較演算子についても同様です。
なんらかの理由で、2 つの文字列リテラルを関係的に比較し、明確に定義された結果を得たい場合は、std::less
比較子を使用できます。これにより、すべてのポインターに対して厳密な順序付けと弱い順序付けが提供されます。std::greater
、std::greater_equal
、およびstd::less_equal
比較子もあります。同じ内容の文字列リテラルが同等に比較されない可能性があることを考えると、なぜこれをやりたいのかわかりませんが、できます。
アイデアは、C++ の文字列リテラルは配列であるということです。配列には比較演算子が定義されていないため、次に最適なポインター比較演算子を使用して比較されます。配列は暗黙的にポインターに減衰するため、比較では内容ではなくアドレスが比較されます。"a" と "b" は同じメモリ位置にあることはできないため、"a" != "b" は真のアサーションです。また、有効な静的アサーションを形成します。"a" == "a" についてそのような保証を行うことはできませんが、-fmerge-constants (-O1 で暗示される) を使用した GCC はかなり強い確率を作成でき、-fmerge-all-constants は保証を与えることができます (潜在的に不適合な行動につながります)。
コンテンツ ベースの比較が必要な場合は、いつでも を使用できますassert(!strcmp("a", "a"))
。または、静的アサーションにある種の constexpr ベースの strcmp を使用できます。
constexpr bool static_strequal_helper(const char * a, const char * b, unsigned len) {
return (len == 0) ? true : ((*a == *b) ? static_strequal_helper(a + 1, b + 1, len - 1) : false);
}
template <unsigned N1, unsigned N2>
constexpr bool static_strequal(const char (&str1)[N1], const char (&str2)[N2]) {
return (N1 == N2) ? static_strequal_helper(&(str1[0]), &(str2[0]), N1) : false;
}
static_assert(static_strequal("asdf", "asdf"), "no error - strings are equal");
static_assert(static_strequal("asdf", "jkl;"), "strings are not equal");
assert(!strcmp("asdf", "jkl;")); //no compile error - runtime error
//cannot use strcmp in static assert as strcmp is not constexpr...
次に、g++ -std=c++0x (gcc >= 4.7 の場合は -std=c++11) でコンパイルし、...
error: static assertion failed: "strings are not equal"