在C++中比较字符数组和字符串字面值

9

我有一个字符数组,想要确定它是否与字符串字面值匹配,例如:

char value[] = "yes";
if(value == "yes") {
   // code block
} else {
   // code block
}

这导致了以下错误:与字符串文字的比较结果未指定行为。我也尝试了类似以下的内容:
char value[] = "yes";
if(strcmp(value, "yes")) {
   // code block
} else {
   // code block
}

这段代码没有产生任何编译错误,但它的运行结果与预期不符。


3
“CString”并不意味着这个。CString是指MFC中的微软字符串类。如果您指的是以空字符结尾的字符数组,那么术语应该是“C字符串”——两个单词,只有语言名称大写。 - Rob Kennedy
@Rob:我已经更正了标题/问题,以反映他正在询问字符数组和字符串字面量的事实。 - luke
4个回答

28

请查看 strcmp 的文档。提示:它不会返回布尔值。

预计完成时间: == 一般不可行,因为 cstr1 == cstr2 比较的是指针,所以只有当 cstr1cstr2 指向相同的内存位置时才会返回 true,即使它们恰好都是按字典序相等的字符串。你尝试过的(将 cstring 与文字量进行比较,例如cstr == "yes")尤其行不通,因为标准不要求这样做。在合理的实现中,我不认为它会出错,但 cstr == "yes" 不太可能成功,因为 cstr 不太可能指向字符串常量 "yes" 所在的地址。


1
+1:唯一一个解释为什么 OP 的第一次尝试失败的人!在我看来,这比解释可以通过阅读 strcmp 手册(或谷歌搜索)在10秒钟内找到的内容更重要。 - Cascabel
不是"不可能的"。在上面的代码中,value不能与字符串字面量在任何符合规范的实现中具有相同的地址。当警告提到未指定行为时,我认为它意味着在不同的位置使用相同的字面量是否会得到相同的地址是未指定的。 - Steve Jessop
@onebyone:真的吗?我认为符合规范的实现允许合并字符串字面量,因此如果你有char* s = "yes";,s == "yes"可能是正确的。 - David Seiler
当然,这是未指定的部分 - 它取决于实现是否为真或假。但在问题的代码中,“value”是一个数组,而不是指针。因此,它的第一个字节没有任何文字或其他对象的第一个字节可以合法地具有相同的地址。这就是为什么当它降级为指针与“yes”进行比较时,它不是“不可能”相等,而是永远不相等的原因。 - Steve Jessop
哦,我明白你的意思了。是的,原帖中的做法永远行不通。 - David Seiler

23

3

strcmp返回一个三状态值,用于指示两个字符串的相对顺序。调用strcmp(a, b)这样的函数时,函数返回:

  • a < b时返回小于0的值
  • a == b时返回0
  • a > b时返回大于0的值

0

由于这个问题标记了,除了David Seilers的优秀解释说明strcmp()在你的情况下为什么不起作用,我想指出,strcmp()通常只适用于空字符结尾的字符数组(来源)。

在你的情况下,你将一个字符串字面量赋值给一个字符数组,这将自动导致一个空字符结尾的字符数组,所以这里没有问题。但是,如果你从一个缓冲区中切割出你的字符数组,它可能不是空字符结尾的。在这种情况下,使用strcmp()是危险的,因为它会遍历内存直到找到一个空字节('\0')来形成一个字符串。

解决你的问题的另一个方法是(使用C++ std::string):

char value[] = "yes";
if (std::string{value} == "yes")) {
    // code block
} else {
    // code block
}

这也仅适用于以空字符结尾的字符数组。如果您的字符数组没有以空字符结尾,请告诉std::string构造函数您的字符数组的长度:

char value[3] = "yes";
if (std::string{value, 3} == "yes")) {
    // code block
} else {
    // code block
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接