11
char s1[] = "0";
char s2[] = "9";
printf("%d\n", strcmp(s1, s2));   // Prints -9
printf("%d\n", strcmp("0", "9")); // Prints -1

为什么 strcmp 在接收到相同的参数时会返回不同的值?

这些值仍然是合法的,因为 strcmp 的手册页说 strcmp 的返回值可以小于、大于或等于 0,但我不明白为什么它们在这个示例中不同。

4

2 回答 2

8

我假设您在编译时使用的是 GCC,我在 4.8.4 上尝试过。这里的诀窍是 GCC 理解某些标准库函数的语义(strcmp作为其中之一)。在您的情况下,编译器将完全消除第二次strcmp调用,因为它知道strcmp给定字符串常量"0"的结果"9"将是负数,并且将使用标准兼容值(-1)而不是进行调用。它不能对第一次调用做同样的事情,因为s1并且s2可能已经在内存中改变了(想象一个中断,或多个线程等)。

您可以做一个实验来验证这一点。将const限定符添加到数组以让 GCC 知道它们不能更改:

const char s1[] = "0";
const char s2[] = "9";
printf("%d\n", strcmp(s1, s2));   // Now this will print -1 as well
printf("%d\n", strcmp("0", "9")); // Prints -1

您还可以查看编译器的汇编器输出(使用-S标志)。

但是,最好的检查方法是使用-fno-builtin,它会禁用此优化。使用此选项,您的原始代码在两种情况下都将打印 -9

于 2015-10-12T22:58:35.860 回答
4

不同之处在于 strcmp 的实现。只要它符合 (<0, 0, >0),对开发人员来说应该无关紧要。你不能依赖其他任何东西。如您所知,源代码可能会确定它应该是负数,并随机生成一个负数来让您失望。

于 2015-10-12T22:52:59.167 回答