在C语言中使用等号操作符 == 比较两个字符串是否相等

20
int main (int argc, **argv)
{
       if (argv[1] == "-hello")
            printf("True\n");
       else
            printf("False\n");
}
# ./myProg -hello
False

为什么会返回False?我知道strcmp(argv[1], "-hello") == 0返回true,但是为什么不能用等号运算符来比较两个C字符串?


1
既然您坚持认为这个问题是一个C问题,我已经用C代码替换了C++代码。如果您坚持使用std::cout,我就坚持使用C++标签。 - JeremyP
1
这个问题肯定是一个精确的重复。 - R.. GitHub STOP HELPING ICE
9个回答

22

因为argv[1](例如)实际上是一个指向字符串的指针,所以你正在比较指针。


17

在C语言中,你不能使用==运算符比较字符串,因为C编译器对于除了字符串字面值之外的字符串并没有真正的了解。

编译器只会把两边的char*作为指针进行比较(即比较指针存储的地址)。


15

C 中,因为在大多数情况下,一个数组会“衰变”成一个指向它第一个元素的指针。

所以,当你有一个数组 "foobar" 并在大多数情况下使用它时,它会衰变成一个指针:

if (name == "foobar") /* ... */; /* comparing name with a pointer */

您希望将数组的内容某些内容进行比较。您可以手动执行此操作。

if ('p' == *("foobar")) /* ... */; /* false: 'p' != 'f' */
if ('m' == *("foobar"+1)) /* ... */; /* false: 'm' != 'o' */
if ('g' == *("foobar"+2)) /* ... */; /* false: 'g' != 'o' */
或者自动执行。
if (strcmp(name, "foobar")) /* name is not "foobar" */;

1
如果字符串相等,strcmp(name,“foobar”)将返回0,因此会将其解析为false。使用“if (strcmp(name,“foobar”)== 0)”将更好。 - Overdrivr
感谢@Overdrivr的提醒。已添加注释以使代码更加清晰明了。 - pmg

6

因为C语言中没有所谓的字符串。

在C语言中,字符串通常是char数组或char指针(几乎相同)。将指针/数组与const数组进行比较将不会得到预期的结果。

更新:我所说的“没有C字符串”是指,在C语言中没有字符串。通常所说的“C字符串”是与语言无关的(就像“Pascal字符串”一样),它是将字符串表示为以null结尾的线性字符数组。


4
确实存在C语言中的C字符串。我不确定你的确切意思。也许是指“C语言中没有C字符串类型”? - Magnus Hoff
那只是滥用术语。那里描述的是一个以空字符结尾的字符串,而不是“Pascal字符串”,后者将大小作为第一个字节给出。 - jv42
现在,C编程语言(就像没有STL的纯C++一样)没有字符串类型。有一个编译器特性,可以自动将双引号“...”之间的文本转换为常量字符数组(以空字符结尾),这导致在处理C/C++中的字符串时非常常见的错误。 - jv42
还有一些字符串库函数,它们操作以空字符结尾的 char 数组。 - David Thornley
3
更准确地说,字符串值由字符序列和一个零终止符组成。这些序列以char数组的形式存储(在C中,字符串文字以char数组的形式存储,在C++中则以const char数组的形式存储)。 - John Bode

5
在C语言中,字符串值(包括字符串字面量)被表示为char数组,并以0终止符结尾。你不能使用==运算符比较数组内容,这种操作在语言中没有被定义。
除非它是sizeof&运算符的操作数,或者当它是一个字符串字面量被用于初始化声明另一个数组时,类型为“N元素数组T”的表达式将隐式转换(衰减)为类型“指向T的指针”,并且表达式的值将是数组的第一个元素的地址。
因此,当您编写以下代码时:
if (argv[1] == "-hello")

编译器会将表达式"-hello"从"7个字符元素的数组"隐式转换为"指向字符的指针"(argv[1]已经是指针类型),而表达式的值是字符'-'地址。因此,==比较的是两个指针值,它们(很可能)永远不会相等,因为"-hello"argv[1](很可能)占据内存中的不同区域。
这就是为什么必须使用库函数如strcmp()来比较字符串值的原因。

在C语言中,字符串值(包括字符串字面量)被表示为char数组,其中包含一个0终止符... - pmg

3
因为C字符串本身并不存在。它们是以\0结尾的字符数组。
等号运算符==将测试数组第一个元素的指针是否相同,而不会按字典顺序进行比较。
另一方面,"-hello" == "-hello"可能返回非零值,但这并不意味着==运算符按字典顺序进行比较。这是由其他事实造成的。
如果您想按字典顺序进行比较,您可以始终这样做:
#define STR_EQ(s1,s2)    \
   strcmp(s1,s2) == 0

我看到你标记为C++。所以你可以这样做:
 std::string arg1 ( argv[1] );
 
 if (arg1 == "-hello"){
    // yeahh!!!
 }
 else{
    //awwwww
 }

有人把标签编辑成了C++,这是错误的。现在已经改回C了。 - user402642

2

在C语言中,字符串不是本地类型。在这个例子中,你正在比较两个指针。一个指向你的第一个参数,另一个是一个静态字符数组,用“-hello”的内容填充。

你应该使用strncmp或类似的函数。


1

当你使用==时,你正在比较指针。也就是说,如果两个操作数引用内存中的同一字符串,则它将返回true。因此,在按字典顺序比较字符串时,它不适用。


0

因为C字符串是字符数组。数组只是指向数组中第一个元素的指针,当你使用==比较两个指针时,它比较它们所指向的内存地址,而不是它们所指向的值。


1
数组不仅仅是指针,天啊。 - detly
@detly:易于犯错,因为数组在几乎任何情况下都会衰变为指针。 - David Thornley
@David Thornley:即便如此,最好还是把术语用对。C语言已经够令人困惑了,如果连基础都搞错了就更糟糕了。 - John Bode
我的措辞有点严厉,对不起。但是事实并非如此。有时会栽倒在这种假设上。 - detly

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