是否有任何编译器的strcmp()返回的值不是-1 0和1?

问题描述 投票:-1回答:3

尽管对strcmp()的行为有一个共同的理解和literature

int strcmp( const char *lhs, const char *rhs );

如果lhs按字典顺序在rhs之前出现,则为负值。

如果lhs和rhs比较相等,则为零。

如果lhs按字典顺序在rhs之后出现,则为正值。

问题是我似乎无法使其返回-1 0和1以外的任何值。

确实,行为与定义相符,但我期望值大于或小于1或-1,因为定义断言结果将是<0、0或> 0,而不是-1 ,0或1。

我在多个编译器中对此进行了测试,结果相同。我想看看不是这样的示例。

sample code

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


int main() 
{  
   printf("%d ", strcmp("a", "a"));
   printf("%d ", strcmp("abc", "aaioioa"));
   printf("%d ", strcmp("eer", "tsdf"));
   printf("%d ", strcmp("cdac", "cdac"));
   printf("%d ", strcmp("zsdvfgh", "ertgthhgj"));
   printf("%d ", strcmp("abcdfg", "rthyuk"));
   printf("%d ", strcmp("ze34", "ze34"));
   printf("%d ", strcmp("er45\n", "io\nioa"));
   printf("%d", strcmp("jhgjgh", "cdgffd"));
}

Result: 0 1 -1 0 1 -1 0 -1 1

c strcmp
3个回答
2
投票

C标准明确指出(C11 §7.24.4.2 The strcmp function):

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

并没有说结果必须大于零或小于零;始终返回strcmp-10的函数符合标准;有时返回大于+1的值的函数也是如此,例如1-270。如果您的代码符合C标准,则不得假设任何一组结果;它只能假设结果的符号正确。

这里是+35的实现-在这里命名为strcmp(),因此可以将结果与str_cmp()-不返回strcmp()-1的结果:

+1

在Mac上运行(macOS Mojave 10.14.6; GCC 9.2.0; Xcode 11.13.1)时,我得到了输出:

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

static int str_cmp(const char *s1, const char *s2)
{
    while (*s1 == *s2 && *s1 != '\0')
        s1++, s2++;
    int c1 = (int)(unsigned char)*s1;
    int c2 = (int)(unsigned char)*s2;
    return (c1 - c2);
}

int main(void) 
{  
   printf("%d ", strcmp("a", "a"));
   printf("%d ", strcmp("abc", "aAioioa"));
   printf("%d\n", strcmp("eer", "tsdf"));

   printf("%d ", str_cmp("a", "a"));
   printf("%d ", str_cmp("abc", "aAioioa"));
   printf("%d\n", str_cmp("eer", "tsdf"));
   return 0;
}

我确实稍稍更改了您的数据-0 1 -1 0 33 -15 变成了"aaioioa"。总体结果没有什么不同(但值33大于原始字符串所得到的值)—根据需要,返回值小于,等于或大于零。

"aAioioa"函数是合法的实现,并且宽松地基于str_cmp()的历史通用实现。它在返回值上稍加注意,但是您可以在p106上找到Brian W Kernighan和Dennis M Ritchie的两个较小变体。strcmp()(1988)—一个使用数组索引,另一个使用指针:

The C Programming Language, 2nd Edn

如果对普通的int strcmp(char *s, char *t) { int i; for (i = 0; s[i] == t[i]; i++) if (s[i] == '\0') return 0; return s[i] - t[i]; } int strcmp(char *s, char *t) { for ( ; *s == *t; s++, t++) if (*s == '\0') return 0; return *s - *t; } 类型进行了签名,并且其中一个字符串包含“重音字符”,则字符的范围为-128 .. -1(或0x80 .. 0xFF),K&R代码可能不会返回预期的结果作为无符号值)。我的char代码中的转换将数据视为str_cmp()(通过转换);由于分配的原因,unsigned char强制转换并不是真正必要的。将两个转换为(int)unsigned char值相减得出的结果范围为int .. -255。但是,现代版本的C库不会像直接返回+255-10那样使用直接减法。

注意,C11标准+1说:

由比较函数§7.24.4 String comparison functionsmemcmpstrcmp返回的非零值的符号由第一对字符值之间的差异的符号确定(均解释为strncmp)在比较对象上有所不同。

您可以看unsigned char。大纲显示:

How do I check if a value matches a string?

请注意与零进行比较如何与您进行的测试使用相同的比较运算符。

您可以(但可能不应该)写:

if (strcmp(first, second) == 0)    // first equal to second
if (strcmp(first, second) <= 0)    // first less than or equal to second
if (strcmp(first, second) <  0)    // first less than second
if (strcmp(first, second) >= 0)    // first greater than or equal to second
if (strcmp(first, second) >  0)    // first greater than second
if (strcmp(first, second) != 0)    // first unequal to second

您仍然会得到相同的结果,但是这样做并不明智;总是比较零更容易,也更统一。

您可以使用以下方法得到-1,0,+1结果:

if (strcmp(first, second) <= -1)    // first less than second
if (strcmp(first, second) >= +1)    // first greater than second

对于无限制的整数(而不是限制为0 .. 255的整数),这是安全的,因为它避免了整数溢出,而减法给出了错误的结果。对于包含8位字符的受限整数,减法溢出不是问题。


3
投票

该规范说,数字必须为负,零或正,但是并不能锁定所需的确切值。该库本身可能以更特定的方式运行。


1
投票

请重新阅读此位

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