什么时候strcmp不会返回-1,0或1?

时间:2012-11-26 19:41:30

标签: c strcmp

从手册页:

  

strcmp()和strncmp()函数返回小于等于的整数   如果找到s1(或其前n个字节),则为或者大于零,   分别小于,匹配或大于s2。

C中的示例代码(在我的机器上打印-15,交换test1和test2将值反转):

#include <stdio.h>
#include <string.h>

int main() {
    char* test1 = "hello";
    char* test2 = "world";
    printf("%d\n", strcmp(test1, test2));
}

我发现this code(取自this question)依赖于strcmp的值不是-1,0和1(它使用{{1}中的返回值})。对我来说,这是一种糟糕的风格,取决于无证的特征。

我想我有两个相关的问题:

  • 除了小于,大于或等于零之外,C标准中还有哪些内容可以定义返回值是什么?如果没有,标准实现会做什么?
  • Linux,Windows和BSD的返回值是否一致?

修改

离开我的电脑5分钟后,我意识到这个代码实际上没有错误。在阅读评论/答案之前,我找出了我想出的部分,但是我把它留在那里以保持评论的相关性。我认为这仍然是一个有趣的问题,并且可能会导致习惯于其他语言的程序员总是返回-1,0或1(例如Python似乎这样做,但是没有这样记录)。

FWIW,我认为依赖记录行为以外的其他东西是不好的风格。

7 个答案:

答案 0 :(得分:7)

  

C标准中是否有某些内容定义了除小于,大于或等于零之外的返回值?

没有。最严格的约束是它应该为零,小于零或大于零,如documentation of this particular function中所述。

  

如果没有,标准实现会做什么?

没有“标准实施”这样的东西。即使有,也可能只是

return zero, less than zero or more than zero;

: - )

  

Linux,Windows和BSD的返回值是否一致?

从10.7.4开始,我可以确认它在Linux和OS X中是一致的(具体来说,它是-1,0或+1)。我不知道Windows,但我敢打赌微软的人会使用-2和+3来破解代码:P

另外,我还要指出,你完全误解了代码的作用。

  

我发现这个代码(取自这个问题)依赖于strcmp的值不是-1,0和1(它使用qsort中的返回值)。对我而言,这是一种糟糕的风格,取决于无证的特征。

不,它实际上没有。 C标准库在设计时考虑了一致性和易用性。也就是说,qsort()要求的是它的比较器函数返回一个负数或正数或零 - 正是strcmp()保证要做的。因此,这不是“糟糕的风格”,它是完全符合标准的代码,不依赖于未记录的功能。

答案 1 :(得分:3)

在c99标准中

7.21.4.2 The strcmp function

&#34; strcmp函数返回一个整数greater than, equal to, or less than zero, 因此,s1指向的字符串大于,等于或小于s2指向的字符串。 &#34;

这意味着标准并不保证-101可能因操作系统而异。

您获得的价值是wh的差异15

根据您的情况helloworld 'h'-'w' = -15 < 0that's why strcmp retuns -15

答案 2 :(得分:3)

•Is there something in the C standard that defines what the return values are besides less than, greater than, or equal to zero? If not, what does the standard implementation do?

不,正如你自己提到的那样,男人说less than, equal to, or greater than zero,这也是标准。

•Is the return value consistent across the Linux, Windows and the BSDs?

没有

在带有gcc的linux(openSuse 12.1,内核3.1)上,我得到-15 / 15,具体取决于test1test2是否是第一个。
在Windows上7(VS 2010)我得到-1 / 1

根据strcmp()的宽松定义,两者都很好。


...that relies on the values of strcmp being something other than -1, 0 and 1 (it uses the return value in qsort).

一个不适合你的有趣方面...如果您查看qsort() strcmp()示例,则与您使用qsort()发布的铃声代码几乎相同,strcmp()所要求的兼容函数实际上是 适合{{1}}的回报:

  

比较函数必须返回小于,等于或的整数   如果第一个参数被认为是大于零   分别小于,等于或大于第二个。

答案 3 :(得分:1)

实际上,strcmp的返回值可能是第一个位置的字节值之间的差异,这仅仅是因为返回此差异比执行其他条件分支更有效将它转换为-1或1.不幸的是,some broken software已知假设结果符合8位,导致serious vulnerabilities。简而言之,除了结果的标志外,你不应该使用任何东西。

有关问题的详细信息,请阅读我上面链接的文章:

https://communities.coverity.com/blogs/security/2012/07/19/more-defects-like-the-mysql-memcmp-vulnerability

答案 4 :(得分:1)

this页面中:

  

strcmp()函数将s1指向的字符串与s2指向的字符串进行比较。   非零返回值的符号由第一对字节值(均被解释为unsigned char类型)的值之间的差异符号确定,这些字符在被比较的字符串中不同。

Here FreeBSD strcmp 的实现。

#include <string.h>

/*
 * Compare strings.
 */
int
strcmp(s1, s2)
    register const char *s1, *s2;
{
    while (*s1 == *s2++)
        if (*s1++ == 0)
            return (0);
    return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}

答案 5 :(得分:0)

从手册页:

  

返回值          如果s1(或前n个字节),strcmp()和strncmp()函数返回小于,等于或大于零的整数   分别找到它们          小于,匹配或大于s2。

它只指定它大于或小于0,没有说明具体值,这些是我想的具体实现。

  

遵守          SVr4,4.3BSD,C89,C99。   这说明它包含在哪些标准中。该函数必须存在且行为与指定的一致,但规范没有说明实际返回的值,因此您不能依赖它们。

答案 6 :(得分:0)

C标准中没有任何内容涉及strcmp()返回的值(即该值的符号除外):

  

7.21.4.2 strcmp功能

     

<强>概要

#include <string.h>
int strcmp(const char *s1, const char *s2);
     

<强>描述

     

strcmp函数比较s1指向的字符串   到s2指向的字符串。

     

<强>返回

     

strcmp函数返回一个大于等于的整数   因此,当s1指向的字符串为时,或者小于零   大于,等于或小于s2指向的字符串。

因此很明显,使用除了返回值的符号以外的任何东西都是不好的做法。