c - 为什么 strcmp 的返回不同?

标签 c strcmp

<分区>

这是我用gcc编译的C代码

char *a="a";
char *d="d";
printf("%d\n", strcmp("a", "d"));
printf("%d\n", strcmp(a, "d"));
printf("%d\n", strcmp(a, d));

当我用 -O 编译时,输出是

-1
-3
-1

当我编译时没有使用 -O 然后输出是

-1
-3
-3

为什么输出不一样,strcmp的代码是什么?

最佳答案

Why the output is different

因为重要的是返回值的符号(正数、负数或零)。 strcmp() 不需要返回+1 或-1,也不需要返回一致的值。我怀疑在第一种和第三种情况下,编译器优化了对 strcmp() 的调用并将 -1 放入返回值的位置。在第二种情况下,我认为该函数实际上被调用了。

what is the code of strcmp?

从它似乎返回第一个不同字符的字符代码之间的差异这一事实推断,我会说这是 glibc 的 strcmp():

int
 strcmp (p1, p2)
      const char *p1;
      const char *p2;
 {
   register const unsigned char *s1 = (const unsigned char *) p1;
   register const unsigned char *s2 = (const unsigned char *) p2;
   unsigned char c1, c2;

   do
     {
       c1 = (unsigned char) *s1++;
       c2 = (unsigned char) *s2++;
       if (c1 == '\0')
     return c1 - c2;
     }
   while (c1 == c2);

   return c1 - c2;
 }

编辑:@AndreyT 不相信我,所以这是为我生成的程序集 GCC 4.2(OS X 10.7.5 64 位 Intel,默认优化级别 - 无标志):

    .section    __TEXT,__text,regular,pure_instructions
    .globl  _main
    .align  4, 0x90
_main:
Leh_func_begin1:
    pushq   %rbp
Ltmp0:
    movq    %rsp, %rbp
Ltmp1:
    subq    $32, %rsp
Ltmp2:
    leaq    L_.str(%rip), %rax
    movq    %rax, -16(%rbp)
    leaq    L_.str1(%rip), %rax
    movq    %rax, -24(%rbp)
    movl    $-1, %ecx             ; <- THIS!
    xorb    %dl, %dl
    leaq    L_.str2(%rip), %rsi
    movq    %rsi, %rdi
    movl    %ecx, %esi
    movq    %rax, -32(%rbp)
    movb    %dl, %al
    callq   _printf               ; <- no call to `strcmp()` so far!
    movq    -16(%rbp), %rax
    movq    %rax, %rdi
    movq    -32(%rbp), %rsi
    callq   _strcmp               ; <- strcmp()
    movl    %eax, %ecx
    xorb    %dl, %dl
    leaq    L_.str2(%rip), %rdi
    movl    %ecx, %esi
    movb    %dl, %al
    callq   _printf               ; <- printf()
    movq    -16(%rbp), %rax
    movq    -24(%rbp), %rcx
    movq    %rax, %rdi
    movq    %rcx, %rsi
    callq   _strcmp               ; <- strcmp()
    movl    %eax, %ecx
    xorb    %dl, %dl
    leaq    L_.str2(%rip), %rdi
    movl    %ecx, %esi
    movb    %dl, %al
    callq   _printf               ; <- printf()
    movl    $0, -8(%rbp)
    movl    -8(%rbp), %eax
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %eax
    addq    $32, %rsp
    popq    %rbp
    ret
Leh_func_end1:

    .section    __TEXT,__cstring,cstring_literals
L_.str:
    .asciz   "a"

L_.str1:
    .asciz   "d"

L_.str2:
    .asciz   "%d\n"

    .section    __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame0:
Lsection_eh_frame:
Leh_frame_common:
Lset0 = Leh_frame_common_end-Leh_frame_common_begin
    .long   Lset0
Leh_frame_common_begin:
    .long   0
    .byte   1
    .asciz   "zR"
    .byte   1
    .byte   120
    .byte   16
    .byte   1
    .byte   16
    .byte   12
    .byte   7
    .byte   8
    .byte   144
    .byte   1
    .align  3
Leh_frame_common_end:
    .globl  _main.eh
_main.eh:
Lset1 = Leh_frame_end1-Leh_frame_begin1
    .long   Lset1
Leh_frame_begin1:
Lset2 = Leh_frame_begin1-Leh_frame_common
    .long   Lset2
Ltmp3:
    .quad   Leh_func_begin1-Ltmp3
Lset3 = Leh_func_end1-Leh_func_begin1
    .quad   Lset3
    .byte   0
    .byte   4
Lset4 = Ltmp0-Leh_func_begin1
    .long   Lset4
    .byte   14
    .byte   16
    .byte   134
    .byte   2
    .byte   4
Lset5 = Ltmp1-Ltmp0
    .long   Lset5
    .byte   13
    .byte   6
    .align  3
Leh_frame_end1:


.subsections_via_symbols

和原始源代码:

#include <stdio.h>
#include <string.h>

int main()
{
    const char *a = "a";
    const char *d = "d";
    printf("%d\n", strcmp("a", "d"));
    printf("%d\n", strcmp(a, "d"));
    printf("%d\n", strcmp(a, d));

    return 0;
}

及其生成的输出(截图以获得更好的证明):

enter image description here

关于c - 为什么 strcmp 的返回不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16454144/

相关文章:

C89 开关盒成套使用

c - 段错误合并排序程序

c - 如何从内部驱动程序代码中读取注册表?

c - 用于读取数据库的损坏的 C 代码

c - 由于 C 中的 strcmp 和 strcpy 导致的程序错误

c - 导致 StrCmp 返回 0 的非 Null 终止值?

c - 将静态库与 C 数学库正确链接

C 程序无法使用用户创建的函数输出正确的值

C 代码 - 从 2D 字符数组中删除重复字的逻辑

c - C 中的字符串比较密码