gcc正在进行递归调用吗?

时间:2014-09-07 09:18:17

标签: c gcc assembly

我正在使用-O3 -x c -std=c99 -fno-builtin -nostdlib -ffreestanding

编译此代码
unsigned char *memset(unsigned char *dest, unsigned char val, int count)
{
    unsigned char* p = dest;
    while (count--)
        *p++ = val;

    return dest;
}

#include <stdio.h>

int main()
{
    unsigned char c[20];
    memset(c, 'a', 19);
    c[19] = '\0';
    printf((const char*) c);
}

并使用godbolt来检查gcc在程序集输出中调用的memset

memset:
    test    edx, edx
    je  .L6
    sub edx, 1
    sub rsp, 8
    movzx   esi, sil
    add rdx, 1
    call    memset
    add rsp, 8
    ret
.L6:
    mov rax, rdi
    ret
main:
    sub rsp, 40
    movabs  rax, 7016996765293437281
    mov QWORD PTR [rsp], rax
    mov QWORD PTR [rsp+8], rax
    mov eax, 24929
    mov WORD PTR [rsp+16], ax
    mov rdi, rsp
    xor eax, eax
    mov BYTE PTR [rsp+18], 97
    mov BYTE PTR [rsp+19], 0
    call    printf
    add rsp, 40
    ret

使用我使用过的标志,我试图消除它调用内置memset的所有可能性,并根据彩色化神棒使用来判断,看起来gcc正在{{进行递归调用1}}。那么它是在进行递归还是调用内置*p++ = val;

1 个答案:

答案 0 :(得分:1)

正如其他人所指出的,数组 c 元素的设置已经内联。结果,你实现的memset()甚至没有被调用。这是使用-03编译器选项的结果。编译器在优化方面非常积极。此外,执行路径上没有递归。

然而,这并不能完全回答你的问题。反汇编输出中显示的memset()确实不是内置版本,甚至没有被执行。

顺便说一下,您不需要应用-fno-builtin标志,因为-ffreestanding标志会自动隐含它。另外,如果启用垃圾收集,我相信会发现反汇编输出中的memset()例程将会消失。