将字符串文字与另一个字符串文字与==
运算符(或!=
)进行比较时,结果是否已明确定义?
例如,以下是否可以保留?
assert("a" == "a");
assert("a" != "b");
请不要说“使用std :: string”之类的内容。我只是想知道这个具体案例。
答案 0 :(得分:15)
"a" == "a"
此表达式可能会产生true
或false
;没有保证。两个"a"
字符串文字可能占用相同的存储空间,也可能存在于内存中的两个不同位置。
我认为C ++标准中最接近的语言是:“所有字符串文字是否都是不同的(即存储在非重叠对象中)是实现定义的”(C ++11§2.14.5/ 12)。没有其他要求或限制,因此结果未指定。
"a" != "b"
此表达式必须产生false
,因为这两个字符串文字无法占据内存中的相同位置:"a"[0] != "b"[0]
。
当您以这种方式比较字符串文字时,您实际上是在比较指向数组中初始元素的指针。
因为我们正在比较指针,所以关系比较(<
,>
,<=
和>=
)比平等比较更有问题({{1因为只能使用关系比较来执行一组受限制的指针比较。}和==
)如果指针指向同一个数组或指向同一个对象的指针,则只能对它们进行关系比较。
如果两个!=
字符串文字在内存中占据相同的位置,那么"a"
将被明确定义并产生"a" < "a"
,因为两个指针都指向初始元素({ {1}})相同的数组。
但是,如果两个false
字符串文字在内存中占用不同的位置,则'a'
的结果是未定义的,因为被比较的两个指针指向完全不相关的对象
由于"a"
和"a" < "a"
永远不会占用内存中的相同位置,因此"a"
始终具有未定义的行为。其他关系比较运算符也是如此。
如果由于某种原因想要关联地比较两个字符串文字并且具有明确定义的结果,那么可以使用"b"
比较器,它对所有指针提供严格弱的排序。还有"a" < "b"
,std::less
和std::greater
比较器。鉴于具有相同内容的字符串文字可能无法比较相等,我不知道为什么会想要这样做,但你可以。
答案 1 :(得分:1)
这个想法是在C ++中字符串文字是数组。由于数组没有为它们定义的比较运算符,因此使用下一个最佳拟合 - 指针比较运算符对它们进行比较,因为数组将隐式衰减到指针,因此任何比较都会比较地址而不是内容。由于“a”和“b”不能在同一个存储位置,“a”!=“b”是一个真正的断言。它还形成一个有效的静态断言。关于“a”==“a”,不能做出这样的保证,尽管GCC使用-fmerge-constants(隐含在-O1)可以产生相当强的概率而-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(或-std = c ++ 11 for gcc&gt; = 4.7)进行编译,然后......
error: static assertion failed: "strings are not equal"