【问题标题】:strcmp in C returns 1 instead of 0C 中的 strcmp 返回 1 而不是 0
【发布时间】:2014-03-18 12:36:43
【问题描述】:

我用 C 编写了以下代码。

#include <stdio.h>
#include <string.h>
int main(void) {
    char str1[4] = "abcd";
    char str2[4] = "abcd";
    printf("%d\n",strcmp(str1,str2));

    return 0;
}

我希望返回值为 0(因为我被告知 strcmp 函数对于相等的字符串返回 0)。但它会打印 1!

Success  time: 0 memory: 2248 signal:0
1

这是一个错误吗?还是我错过了什么?

【问题讨论】:

  • 在编译器中启用警告。如果这没有帮助,请使用更好的编译器。

标签: c string comparison string-comparison strcmp


【解决方案1】:

因为你的数组不够长。您没有考虑字符串的零终止符。您的字符串需要 5 个字符,字符串本身需要 4 个字符,零终止符需要 1 个字符。

写:

char str1[5] = "abcd";
char str2[5] = "abcd";

顺便说一句,我想知道为什么您的编译器没有发出警告或发出警告?

【讨论】:

  • 确实如此。长度为 4 的数组具有从 0 到 3 的索引。您需要为尾随零留出空间,因此您的数组需要 5 长。
  • 或者你可以写char str1[] = "abcd";让编译器计算长度(5)。
  • @ButaniVijay:C 中没有“越界”异常。如果你写得比最后一个索引更远,数组后面的内存将被覆盖,然后任何事情都可能发生。
  • @shivamtiwari93 终结者\0 isn't taken into account for strlen
  • (很可能它只复制了 4 个字符到数组中,而没有受到终止符的影响,并且您正在比较两个未终止且很可能重叠的字符串)
【解决方案2】:

你的一个字符串在内存中看起来像这样:'a' 'b' 'c' 'd' '\0'。也就是说,就像每个字符串一样,它以 '\0' 结尾,它是一个类似于 'a' 或 'b' 的字符。因此,您需要五个字符的空间来存储字符串“abcd”,并且必须通过 char str1[5] 声明它。

【讨论】:

  • @ButaniVijay:因为 C 编译器不检查是否违反数组边界。提供足够大的数组是程序员的唯一责任。
  • @ButaniVijay 它是C,而不是java
【解决方案3】:

要么为数组提供正确的大小,要么让编译器为你做所有事情

 char str1[] = "abcd";
 char str2[] = "abcd";

在这种情况下,编译器将为您的字符串提供足够的空间。

【讨论】:

    【解决方案4】:

    (由帕斯卡·库克提供)

    C99 标准 §6.7.8.¶14 说

    字符类型的数组可以由字符串初始化 字面量,可选地用大括号括起来。的连续字符 字符串文字(包括终止空字符 if 有空间或数组大小未知)初始化 数组的元素。

    由于字符串由空字节'\0' 终止,因此字符串文字"abcd" 中的实际字符数为5。数组str1str2 的大小为4。因此,它们不能保存空字节,实际上它们不是字符串。以下语句是等价的。

    char str1[4] = "abcd";
    char str1[4] = {"abcd"}
    char str1[4] = {'a', 'b', 'c', 'd'};
    

    str1str2 传递给strcmp 会调用未定义的行为,因为它们不是字符串。 strcmp 将溢出str1str2 指向的缓冲区,因为它找不到终止的空字节。这是未定义的行为,可能会由于段错误导致程序崩溃。

    字符串是由空字节'\0' 终止的字符数组。因此,字符串文字"abcd" 的长度是5 而不是4。请注意,标准库函数strlen 不计算空字节,因此在这种情况下,strlen("abcd") 返回4

    当您使用字符串文字初始化数组时,最好将数组大小留空,该数组大小会自动确定为足够大以存储初始化字符串中的所有字符。

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        char str1[] = "abcd";
        char str2[] = "abcd";
        printf("%d\n", strcmp(str1, str2));  // prints 0
    
        return 0;
    }
    

    【讨论】:

    • “未定义的行为,因为字符数组 str1 和 str2 不足以容纳初始化它们的字符串文字”不,错误。标准说:“一个字符类型的数组可以由一个字符串字面量初始化,可选地用大括号括起来。字符串文字的连续字符(如果有空间或数组大小未知,则包括终止的空字符)初始化数组的元素。” C99 6.7.8:14。将str1 传递给strcmp 是未定义的行为,但char str1[4] = "abcd"; 不是。
    • @PascalCuoq 谢谢。学到了新东西。我已经更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2012-01-05
    • 1970-01-01
    • 2022-12-16
    • 1970-01-01
    • 1970-01-01
    • 2017-11-08
    • 1970-01-01
    • 2015-10-18
    相关资源
    最近更新 更多