strcmp何时不返回-1、0或1?

问题描述 投票:2回答:7

从手册页:

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(它使用qsort中的返回值)。对我来说,这是可怕的风格,取决于未记录的功能。

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

  • C标准中是否有定义小于,大于或等于零的返回值的东西?如果不是,那么标准实现有什么作用?
  • 返回值在Linux,Windows和BSD上是否一致?

编辑:

离开计算机5分钟后,我意识到所讨论的代码实际上没有错误。在阅读评论/答案之前,我剔除了我想出的部分,但是我把它们留在那里以保持评论的相关性。我认为这仍然是一个有趣的问题,可能会对习惯于总是返回-1、0或1的其他语言的程序员造成困扰(例如,Python似乎可以做到这一点,但并未以这种方式记录下来)。

FWIW,我认为仅依靠已记录的行为以外的其他方式是不好的方式。

c strcmp
7个回答
3
投票

在C99标准中,§7.21.4.2 The strcmp function

strcmp函数返回整数大于,等于或小于零,因此,由于strcmp指向的字符串大于,等于或小于s1指向的字符串。

已添加强调。]

这表示标准不保证s2-10;它可能会因操作系统而异。

您得到的值是1w之间的差h

在您的情况下为15hello,因此world,这就是'h'-'w' = -15 < 0返回-15的原因。


7
投票

C标准中是否有定义小于,大于或等于零的返回值的东西?

没有最严格的约束是,它应该为零,小于零或大于零,如strcmp中所指定。

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

没有“标准实现”之类的东西。即使有,也可能只是

documentation of this particular function

:-)

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

我可以确认从10.7.4版开始,它在Linux和OS X上都是一致的(特别是-1、0或+1)。我对Windows一无所知,但我敢打赌Microsoft家伙使用-2和+3只是为了破坏代码:P

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

我发现此代码(取自该问题)依赖于strcmp的值,而不是-1、0和1(它使用qsort中的返回值)。对我来说,这是可怕的风格,取决于未记录的功能。

不,实际上不是。 C标准库的设计考虑了一致性和易用性。也就是说,return zero, less than zero or more than zero; 要求其比较器函数返回一个负数或一个正数或零-正是qsort()所保证的。因此,这不是“糟糕的样式”,它是完全符合标准的代码,不依赖于未记录的功能。


3
投票

•C标准中是否有定义小于,大于或等于零的返回值的东西?如果不是,那么标准实现有什么作用?

不,正如您提到的那样,手册页上显示的是strcmp(),这也是标准所说的。

•返回值在Linux,Windows和BSD上是否一致?

编号

在具有gcc的Linux(OpenSuSE 12.1,内核3.1)上,我得到less than, equal to, or greater than zero / -15取决于15test1是第一个。在Windows 7(VS 2010)上,我得到test2 / -1

基于1的宽松定义,两者都很好。


...依赖于strcmp的值不是-1、0和1(它使用qsort中的返回值)。

为您提供的有趣的旁注...如果您查看strcmp()手册页,该示例与您使用qsort()发布的Bell代码几乎相同。原因是qsort()所需的比较器函数实际上是great适合strcmp()的返回值:

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


1
投票

实际上,qsort()的返回值很可能是第一个位置的字节值之间的差异,仅是因为返回此差异比执行附加条件分支对其进行转换要有效得多。到-1或1。不幸的是,已知strcmp()假定结果适合8位,从而导致strcmp。简而言之,除了结果的符号外,您永远不要使用其他任何东西。

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

some broken software


1
投票

serious vulnerabilities页中:

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

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

strcmp的实现。
this

0
投票

从手册页:


0
投票

C标准中没有任何内容讨论Here返回的值(也就是说,该值的sign

© www.soinside.com 2019 - 2024. All rights reserved.