+1 到 Gui13 以提供 gcc stdlib strcmp 源的链接 (http://sourceware.org/git/?p=glibc.git;a=blob;f=string/strcmp.c;h= bd53c05c6e21130b091bd75c3fc93872dd71fe4b;hb=HEAD)!
你说得对,strcmp 永远不会比直接比较快[1],但问题是,编译器会优化它吗?我不敢尝试测量它,但我对它的简单程度感到惊喜。我的示例代码是(省略标题):
bool isEmpty(char * str) {
return 0==std::strcmp(str,"");
}
bool isEmpty2(char * str) {
return str[0]==0;
}
我尝试编译它,首先使用gcc -S -o- emptystrcmptest.cc,然后使用gcc -S -O2 -o- emptystrcmptest.cc。令我惊喜的是,虽然我不能很好地阅读程序集,但未优化的版本清楚地显示了差异,优化的版本清楚地显示了两个函数产生了相同的程序集。
所以,我想说,一般来说,没有必要担心这种优化水平。
如果您正在为嵌入式系统使用编译器并且知道它不能处理这种简单的优化(或根本没有标准库),请使用手工编码的特殊情况版本。
如果您正常编码,请使用更易读的版本(恕我直言,可能是 strcmp 或 strlen 或 [0]==0,具体取决于上下文)。
如果您正在编写高效的代码,您希望每秒被调用数千或数百万次,(a) 测试实际上效率更高,(b) 如果可读版本实际上太慢,请尝试编写一些将编译为更好的程序集。
gcc -S -o- emptystrcmptest.cc:
.file "emptystrcmptest.cc"
.section .rdata,"dr"
LC0:
.ascii "\0"
.text
.align 2
.globl __Z7isEmptyPc
.def __Z7isEmptyPc; .scl 2; .type 32; .endef
__Z7isEmptyPc:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
movl $LC0, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call _strcmp
movl %eax, -4(%ebp)
cmpl $0, -4(%ebp)
sete %al
movzbl %al, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
leave
ret
.align 2
.globl __Z8isEmpty2Pc
.def __Z8isEmpty2Pc; .scl 2; .type 32; .endef
__Z8isEmpty2Pc:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
cmpb $0, (%eax)
sete %al
movzbl %al, %eax
popl %ebp
ret
emptystrcmptest.cc:10:2: warning: no newline at end of file
.def _strcmp; .scl 2; .type 32; .endef
gcc -S -O2 -o- emptystrcmptest.cc:
.file "emptystrcmptest.cc"
emptystrcmptest.cc:10:2: warning: no newline at end of file
.text
.align 2
.p2align 4,,15
.globl __Z7isEmptyPc
.def __Z7isEmptyPc; .scl 2; .type 32; .endef
__Z7isEmptyPc:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
popl %ebp
cmpb $0, (%eax)
sete %al
movzbl %al, %eax
ret
.align 2
.p2align 4,,15
.globl __Z8isEmpty2Pc
.def __Z8isEmpty2Pc; .scl 2; .type 32; .endef
__Z8isEmpty2Pc:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
popl %ebp
cmpb $0, (%eax)
sete %al
movzbl %al, %eax
ret
[1] 尽管要小心——在比对零进行直接测试更复杂的情况下,库和编译器代码通常会比手工编写的代码更好。