传递字符串的指针或文字不一致时strcmp()的返回值 [英] Inconsistent strcmp() return value when passing strings as pointers or as literals
问题描述
我在玩弄 STRCMP
时,我注意到这一点,这里是code:
的#include<&string.h中GT;
#包括LT&;&stdio.h中GT;诠释主(){ //传球直接串
的printf(%d个\\ N,STRCMP(艾哈迈德,澄波)); //传递字符串的指针
字符* A =艾哈迈德;
char *之B =澄波;
的printf(%d个\\ N,STRCMP(A,B)); 返回0;}
的输出是:
-1
-5
不应该 STRCMP
工作一样吗?为什么,我定当我通过字符串作为艾哈迈德不同的值
或的char * A =艾哈迈德
。当值传递给函数他们是在它的堆栈分配权?
您最有可能看到一个编译器优化的结果。如果我们测试使用的godbolt 海湾合作委员会code,用 -O0
优化级别,我们可以看到第一种情况下它不叫 STRCMP
:
MOVL $ -1%ESI#
MOVL $ .LC0,EDI%#,
MOVL $ 0,%EAX#
调用printf#
由于您使用的是常量作为参数传递给 STRCMP 编译器能够用于执行常量折叠并调用的编译器的内部在编译时并生成 1
然后,而不必调用 STRCMP
在这是在标准库实现,将会有不同的实现,那么一个可能的更简单的编译时间 STRCMP $ C $运行时间C>。
在第二种情况下它产生一个呼叫 STRCMP
:
通话STRCMP#
MOVL%EAX,ESI%#D.2047,
MOVL $ .LC0,EDI%#,
MOVL $ 0,%EAX#
调用printf#
这是与 GCC有STRCMP 一个一个内置的事实一致>,这是 GCC
常量折叠时将使用。
如果我们进一步<一个href=\"http://gcc.godbolt.org/#%7B%22version%22%3A3%2C%22filterAsm%22%3A%7B%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue%2C%22colouriseAsm%22%3Atrue%7D%2C%22compilers%22%3A%5B%7B%22sourcez%22%3A%22MQSwdgxgNgrgJgUwAQB4DOAXOID2A6ACwD4AoUSWRVTAJ3AHNDSTwMkBbAQ3AAoBKAN4kSSUUgD04gA6c0aBkloM0SbDQQQMUAJ4ixUumAwAzHgCIApHAA6YMwBpFGGhHZTznAlzgOkZ45wYCFxmfHwA3MJiEtKy8mD0Tob0KrJIUjisCDQqeqIQBJw0SABUnAC8fp7eZpHRBUWlAEaV%2FoHBnLV56YYm5la2DrSu7pz2TWGR3eoYMDRgSAAMUwC%2BQAA%3D%22%2C%22compiler%22%3A%22%2Fopt%2Fgcc-4.9.0%2Fbin%2Fg%2B%2B%22%2C%22options%22%3A%22-x%20c%20-std%3Dc99%20-O3%20-fverbose-asm%20-fno-inline-small-functions%22%7D%5D%7D\"相对=nofollow>测试使用 -O1
优化级别或更高 GCC
是能够同时折叠案件的结果将是 1
两种情况:
MOVL $ -1%ESI#
MOVL $ .LC0,EDI%#,
xorl%EAX,EAX%#
调用printf#
MOVL $ -1%ESI#
MOVL $ .LC0,EDI%#,
xorl%EAX,EAX%#
调用printf#
随着越来越多的优化选项中启用了优化器能够确定 A
和 B
指向在已知常数编译时间还有,也可以在编译时计算 STRCMP
的这种情况下,结果也是如此。
我们可以证实, GCC
由具有的 - 这将产生FNO,内置标志,并观察到 STRCMP
对于所有的情况。
铛
略有不同,它不折都使用 -O0
,但将在<$倍C $ C> -O1 及以上两者。
请注意,任何负面的结果是完全符合的,我们可以通过将C99的标准草案 7.21.4.2
的STRCMP功能,它说(的看重点煤矿的):
INT STRCMP(为const char * S1,为const char * S2);
该STRCMP函数返回一个整数大于,等于,或更低
大于零,因此作为字符串指向S1大于,
由S2等于或小于字符串指出。
块引用>technosurus指出,
STRCMP
指定处理字符串,如果他们分别组成的 unsigned char型的,这是覆盖在C99下<的code> 7.21.1 它说:
有关在本节的所有功能,每一个字符应
除preTED,如果它有unsigned char类型(因此每
可能的对象重新presentation是有效的,具有不同的值)。
块引用>I was playing around with
strcmp
when I noticed this, here is the code:#include <string.h> #include <stdio.h> int main(){ //passing strings directly printf("%d\n", strcmp("ahmad", "fatema")); //passing strings as pointers char *a= "ahmad"; char *b= "fatema"; printf("%d\n",strcmp(a,b)); return 0; }
the output is:
-1 -5
shouldn't
strcmp
work the same? Why is it that I am given different value when I pass strings as"ahmad"
or aschar* a = "ahmad"
. When you pass values to a function they are allocated in its stack right?解决方案You are most likely seeing the result of a compiler optimization. If we test the code using gcc on godbolt, with
-O0
optimization level, we can see for the first case it does not callstrcmp
:movl $-1, %esi #, movl $.LC0, %edi #, movl $0, %eax #, call printf #
Since your are using constants as arguments to strcmp the compiler is able for perform constant folding and call a compiler intrinsic at compile time and generate the
-1
then, instead of having to callstrcmp
at run-time which is implemented in the standard library and will have a different implementation then a likely more simple compile timestrcmp
.In the second case it does generate a call to
strcmp
:call strcmp # movl %eax, %esi # D.2047, movl $.LC0, %edi #, movl $0, %eax #, call printf #
This is consistent with the fact that gcc has a builtin for strcmp, which is what
gcc
will use during constant folding.If we further test using
-O1
optimization level or greatergcc
is able to fold both cases and the result will be-1
for both cases:movl $-1, %esi #, movl $.LC0, %edi #, xorl %eax, %eax # call printf # movl $-1, %esi #, movl $.LC0, %edi #, xorl %eax, %eax # call printf #
With more optimizations options turned on the optimizer is able to determine that
a
andb
point to constants known at compile time as well and can also compute the result ofstrcmp
for this case as well during compile time.We can confirm that
gcc
is using builtin function by building with the -fno-builtin flag and observing that a call tostrcmp
will be generated for all cases.
clang
is slightly different in that it does not fold at all using-O0
but will fold at-O1
and above for both.Note, that any negative result is an entirely conformant, we can see by going to the draft C99 standard section
7.21.4.2
The strcmp function which says (emphasis mine):int strcmp(const char *s1, const char *s2);
The strcmp function returns an integer greater than, equal to, or less than zero, accordingly as the string pointed to by s1 is greater than, equal to, or less than the string pointed to by s2.
technosurus points out that
strcmp
is specified to treat the strings as if they were composed of unsigned char, this is covered in C99 under7.21.1
which says:For all functions in this subclause, each character shall be interpreted as if it had the type unsigned char (and therefore every possible object representation is valid and has a different value).
这篇关于传递字符串的指针或文字不一致时strcmp()的返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!