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

从手册页:

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

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

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

我发现这个代码 (取自这个问题 )依赖于strcmp的值不是-1,0和1(它使用qsort的返回值)。 对我来说,这是一种可怕的风格,取决于无证的function。

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

  • C标准中是否有某些内容定义了返回值除了小于,大于或等于零之外的值? 如果没有,标准实现有什么作用?
  • 整个Linux,Windows和BSD的返回值是否一致?

编辑:

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

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

在c99标准

 7.21.4.2 The strcmp function 

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

这意味着标准不保证-11它可能根据操作系统而变化。

你得到的值是wh的差值,即15

在你的情况下helloworld所以'h'-'w' = -15 < 0 that's why strcmp retuns -15

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

不会。最严格的限制是它应该为零,小于零或大于零, 如此特定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中的返回值)。 对我来说,这是一种可怕的风格,取决于无证的function。

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

•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()需要的compairator函数实际上非常适合从strcmp()返回:

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

实际上, strcmp的返回值可能是第一个位置的字节值之间的差异,这仅仅是因为返回此差异比执行额外的条件分支将其转换为-1或不幸的是,已知一些破碎的软件假设结果符合8位,导致严重的漏洞 。 简而言之,除了结果的标志外,你不应该使用任何东西。

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

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

在此页面中:

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

这是FreeBSDstrcmp的一个实现。

 #include  /* * 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)); } 

从手册页:

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

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

符合SVr4,4.3BSD,C89,C99。 这说明它包含在哪些标准中。 该函数必须存在并且按指定的方式运行,但规范没有说明实际的返回值,因此您不能依赖它们。

C标准中没有任何内容可以讨论strcmp()返回的值(即除了该值的符号之外 ):

7.21.4.2 strcmp函数

概要

 #include  int strcmp(const char *s1, const char *s2); 

描述

strcmp函数将s1指向的字符串与s2指向的字符串进行比较。

返回

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

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