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,但我不明白为什么它们在这个示例中不同。
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,但我不明白为什么它们在这个示例中不同。
我假设您在编译时使用的是 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
不同之处在于 strcmp 的实现。只要它符合 (<0, 0, >0),对开发人员来说应该无关紧要。你不能依赖其他任何东西。如您所知,源代码可能会确定它应该是负数,并随机生成一个负数来让您失望。