[英]is this a good way to do a strcmp to return false when strings are empty
[英]Inconsistent strcmp() return value when passing strings as pointers or as literals
当我注意到这个时,我正在玩strcmp
,这里是代码:
#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;
}
输出是:
-1
-5
不应该strcmp
工作相同? 为什么当我将字符串作为"ahmad"
或char* a = "ahmad"
传递给我时,我被赋予不同的值。 将值传递给函数时,它们是否在其堆栈中分配?
您很可能会看到编译器优化的结果。 如果我们在godbolt上使用gcc测试代码 ,使用-O0
优化级别,我们可以看到第一种情况它不调用strcmp
:
movl $-1, %esi #,
movl $.LC0, %edi #,
movl $0, %eax #,
call printf #
由于你使用常量作为strcmp的参数,编译器能够执行常量折叠并在编译时调用编译器内在函数并生成-1
,而不必在运行时调用strcmp
,这是在标准库中实现的将有一个不同的实现,然后可能更简单的编译时间strcmp
。
在第二种情况下,它确实生成对strcmp
的调用:
call strcmp #
movl %eax, %esi # D.2047,
movl $.LC0, %edi #,
movl $0, %eax #,
call printf #
这与gcc具有strcmp内置的事实是一致的,这是gcc
在常量折叠期间将使用的内容。
如果我们进一步测试使用-O1
优化级别或更高的 gcc
能够折叠两种情况,结果将为-1
两种情况:
movl $-1, %esi #,
movl $.LC0, %edi #,
xorl %eax, %eax #
call printf #
movl $-1, %esi #,
movl $.LC0, %edi #,
xorl %eax, %eax #
call printf #
通过启用更多优化选项,优化器能够确定a
和b
指向编译时已知的常量,并且还可以在编译期间计算此情况的strcmp
结果。
我们可以通过使用-fno-builtin标志构建并观察将为所有情况生成对strcmp
的调用来确认gcc
正在使用内置函数。
clang
略有不同,因为它根本不会使用-O0
折叠,但会在-O1
和以上折叠。
注意,任何负面结果都是完全一致的,我们可以通过参考草案C99标准部分7.21.4.2
strcmp函数( 强调我的 ):
int strcmp(const char *s1, const char *s2);
strcmp函数返回一个大于,等于或小于零的整数,因为s1指向的字符串大于,等于或小于 s2指向的字符串 。
technosurus指出strcmp
被指定为将字符串视为由unsigned char组成,这在C99 7.21.1
有所说明:
对于本子条款中的所有函数,每个字符都应解释为它具有unsigned char类型(因此每个可能的对象表示都是有效的并且具有不同的值)。
我认为你相信strcmp
返回的值应该以某种方式依赖于传递给它的输入字符串,这种方式不是由函数规范定义的。 这是不正确的。 例如,参见POSIX定义:
http://pubs.opengroup.org/onlinepubs/009695399/functions/strcmp.html
完成后,如果s1指向的字符串分别大于,等于或小于s2指向的字符串,strcmp()将返回大于,等于或小于0的整数。
这正是你所看到的。 实现不需要对确切的返回值做出任何保证 - 只有在适当的时候小于零,等于零或大于零。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.