在C语言中比较两个char*和两个char[]字符串

3
#include <stdio.h>

int main(){
    char a[] = "bar";
    char b[] = "bar";
    printf("%d\n", (a==b));

    char* x = "bar";
    char* y = "bar";
    printf("%d\n", (x==y));
 }  

输出:

0 
1

我知道我们不能使用==运算符比较C字符数组,因为它比较的是内存位置,但是为什么在第二种情况下它可以工作?

1
它在第一个情况下起作用,因为编译器识别两个“bar”字符串文字相同,并决定通过共享存储并让a和b都指向它来节省空间。虽然我不知道为什么它在x和y的情况下没有这样做。 - Alexander
如何在GCC中将重复或多次出现的字符串文字合并为一个字符串?为什么在C语言中“a” != “a”?C语言中字符串文字的优化。 - phuclv
3个回答

5
在第一种情况下,由于你定义了两个数组,编译器为它们分配了两个不同的存储空间,所以a和b是不相等的。
但是,在第二种情况下,由于你用相同的字符串字面量初始化了两个指针,编译器认为它们是相同的字符串,并将这两个指针指向相同的地址,即该字符串字面量("bar")的起始地址。然而,正如@David所说,这并不一定发生,在某些情况下,通过移除一些优化或基于某些编译器,x和y可能不相同。

你应该指出,xy不一定指向相同的地址。 - ad absurdum
我快速地运行了代码作为经验测试,并且我没有发现“bar”指向相同的内存位置。 - Bennett Yeo
@BennettYeo,请在我的帖子中加粗。 - OmG

3
输出结果是有意义的,因为数组的内存存储不相等。对于字符(char)类型,它们的字面值进行比较。尝试运行这个示例。
int main(void) {
    char a[] = "bar";
    char b[] = "bar";

    printf("Arrays Test: %x == %x ? %d\n",&a,&b,(a==b));


    char* x = "bar";
    char* y = "bar";

    printf("Literals Test: %x == %x ? %d, however x == y ? %d\n",&x,&y, (&x==&y),(x==y));

    return 0;
}

这个在线运行的示例显示 char 的内存引用不相同。

如果您想查看数组的内容是否相等,您需要手动调用数组中的每个 char 并将其与次级数组进行比较。通过将数组的大小相互比较,您可能可以更快地结束执行。

另一个要点是在这个比较范围内,“指针化”字符或数组没有任何区别。


1

这是与实现相关的。

在第一种情况下,ab具有单独的存储空间,因此它们的地址不相等。

然而,编译器可能会识别指向的字符串 xy 是相同的,所以它可能通过使它们指向相同的位置来进行优化,因为您无法修改它。但是,由于标准不要求这样做,您不能依赖结果。这是一种可选的优化。编译器仍然可以生成两个相同的字符串,并使 xy 分别指向它们。


1
不是未定义行为,因为xy都包含有效地址;只是实现相关的。 - ad absurdum
@DavidBowling 去获取一些参考资料。 - iBug
2
一个引用是什么?指针xy是明确定义的,无论编译器为它们存储一个还是两个字符串,并且指针比较是有效的。没有未定义行为。如果让你放心的话,你可以查看Annex J.2中未定义行为的列表,以确定这不在其中列出 ;) - ad absurdum

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