Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/129.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;比较两个字符串文本_C++_String Literals - Fatal编程技术网

C++ C++;比较两个字符串文本

C++ C++;比较两个字符串文本,c++,string-literals,C++,String Literals,使用=运算符(或!=)将一个字符串文字与另一个字符串文字进行比较时,结果定义是否正确 例如,以下各项是否保证有效 assert("a" == "a"); assert("a" != "b"); 请不要说“使用std::string”之类的话。我只想知道这个具体案例 此表达式可能产生true或false;没有任何保证。两个“a”字符串文字可能占用相同的存储空间,也可能存在于内存中的两个不同位置 我认为C++标准中最接近的语言是:“所有的字符串文字是不同的(即,存储在不重叠的对象中)是实现定义的”

使用
=
运算符(或
!=
)将一个字符串文字与另一个字符串文字进行比较时,结果定义是否正确

例如,以下各项是否保证有效

assert("a" == "a");
assert("a" != "b");
请不要说“使用std::string”之类的话。我只想知道这个具体案例

此表达式可能产生
true
false
;没有任何保证。两个
“a”
字符串文字可能占用相同的存储空间,也可能存在于内存中的两个不同位置

我认为C++标准中最接近的语言是:“所有的字符串文字是不同的(即,存储在不重叠的对象中)是实现定义的”(C++ 11×2.145/12)。没有其他要求或限制,因此未指定结果

此表达式必须产生
false
,因为这两个字符串文字无法在内存中占据相同的位置:
“a”[0]!=“b”[0]


以这种方式比较字符串文字时,实际上是在比较指针和数组中的初始元素

因为我们在比较指针,关系比较(
=
)比相等比较(
=
!=
)问题更大,因为使用关系比较只能执行一组受限的指针比较。只有当两个指针都是指向同一数组的指针或指向同一对象的指针时,才能对它们进行关系比较

如果两个
“a”
字符串文字在内存中占据相同的位置,那么
“a”
将是定义良好的,并将产生
false
,因为两个指针都指向同一数组的初始元素(
'a'

但是,如果两个
“a”
字符串文字在内存中占据不同的位置,则
“a”
的结果是未定义的,因为要比较的两个指针指向完全不相关的对象

因为
“a”
“b”
永远不能占用内存中的相同位置,
“a”
始终具有未定义的行为。其他关系比较运算符也是如此


如果出于某种原因,确实希望以关系方式比较两个字符串文本并获得定义良好的结果,则可以使用
std::less
比较器,它为所有指针提供严格的弱排序。还有
std::greater
std::greater_equal
std::less_equal
比较器。考虑到相同内容的字符串文本可能不相等,我不知道为什么会有人想要这样做,但是你可以。

< P> > C++中的字符串文字是数组。由于数组没有为其定义比较运算符,因此将使用下一个最佳匹配-指针比较运算符对其进行比较,因为数组将隐式衰减为指针,因此任何比较都会比较地址而不是内容。由于“a”和“b”不能位于同一内存位置,“a”!=“b”是一个真实的断言。它还形成一个有效的静态断言。对于“a”==“a”不能做出这样的保证,尽管带有-fmerge常数的GCC(隐含在-O1处)可以产生相当强的概率,-fmerge all常数可以为您提供保证(可能导致不符合行为)

如果您碰巧需要基于内容的比较,则始终可以使用
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...

你为什么要这么做?对于保证为假,请尝试断言(!“消息在此显示”)@chris:好奇是其中之一。也适用于类似枚举的类实现思想。定义的实现可能重复,afaik;as==比较const char*S的地址。我认为如果您还可以讨论小于const char*S的比较(定义不太明确)和
std::øess
&friends@Cheersandhth.-阿尔夫:好主意;补充。另外,我不知道我是否提到过这一点,但我喜欢你将“干杯和hth”合并到你的名字中,以解决grumpier堆栈溢出问题
"a" != "b"
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...
error: static assertion failed: "strings are not equal"