printf是否使用C中的堆栈帧?

printf是否使用C中的堆栈帧?,c,stack,printf,C,Stack,Printf,假设我们创建了一个用户函数void func()。 每当在其他函数(如main中调用时,func的堆栈帧都会通过函数调用进行分配 它与printf相同吗? printf是否也使用堆栈帧?函数的堆栈帧由该函数保留;当然,没有其他函数可以知道另一个函数的堆栈使用需求 因此,当您从main()调用func()时,func()中的代码(有时称为“序言”)将保留该函数所需的堆栈空间 是的,这适用于所有函数,包括printf()函数的堆栈帧由该函数保留;当然,没有其他函数可以知道另一个函数的堆栈使用需求 因

假设我们创建了一个用户函数void func()。 每当在其他函数(如main中调用时,func的堆栈帧都会通过函数调用进行分配

它与printf相同吗?
printf是否也使用堆栈帧?

函数的堆栈帧由该函数保留;当然,没有其他函数可以知道另一个函数的堆栈使用需求

因此,当您从
main()
调用
func()
时,
func()
中的代码(有时称为“序言”)将保留该函数所需的堆栈空间


是的,这适用于所有函数,包括
printf()

函数的堆栈帧由该函数保留;当然,没有其他函数可以知道另一个函数的堆栈使用需求

因此,当您从
main()
调用
func()
时,
func()
中的代码(有时称为“序言”)将保留该函数所需的堆栈空间


是的,这适用于所有函数,包括
printf()

前提:堆栈帧只是许多C实现的一个实现细节(具体来说,它通常在x86上使用);它既不是C标准所需要的(C标准对堆栈一无所知),也不是所有实现所需要的(甚至不是,它甚至可能取决于编译器标志/优化器的考虑)

当然,库函数最终只是已经编译到标准库中的常规函数,因此在这方面没有什么特别之处:在使用堆栈帧的实现中,每当执行函数调用时,被调用函数都会设置其堆栈帧(除非它是内联的或完全不重要,但对于像
printf
这样的库函数,通常不会发生这种情况)


不过,这也没什么好担心的——当函数返回时,新的堆栈帧将被丢弃,其堆栈空间将再次可用,因此您不必小心不要调用太多函数。

前提:堆栈帧只是许多C实现的一个实现细节(具体来说,它通常在x86上使用);它既不是C标准所要求的(C标准对堆栈一无所知),也不是所有实现所需要的(甚至不是,它甚至可能取决于编译器标志/优化器的考虑)

当然,库函数最终只是已经编译到标准库中的常规函数,因此在这方面没有什么特别之处:在使用堆栈帧的实现中,每当执行函数调用时,被调用函数都会设置其堆栈帧(除非它是内联的或完全不重要,但对于像
printf
这样的库函数,通常不会发生这种情况)


不过,这也没什么好担心的——当函数返回时,新的堆栈帧被丢弃,其堆栈空间再次可用,因此您不必小心不要调用太多函数。

这里是一个带有
main
的小代码,它调用了一个名为
func
的简单函数

我们可以使用
gcc main.c-S main.S
编译这个c代码。main.S应该是一个程序集输出

在程序集中,您可能会看到CPU指令:push、pop、leave、enter。这些指令负责堆栈帧管理

如果使用gcc和其他选项进行编译,您可能会注意到一些堆栈管理差异

#include <stdio.h>

int func(void);

int func(void)
{
    int i;

    for(i=0;i<100;i++)
        printf("%d",i);

    return i;
}

int main(void)
{
    return func();
}
这里函数
func
objdump main.o-S
).main.o的objdump输出是通过以下方式获得的:
gcc main.c-o main.o

000000000040052d <func>:
  40052d:   55                      push   %rbp
  40052e:   48 89 e5                mov    %rsp,%rbp
  400531:   48 83 ec 10             sub    $0x10,%rsp
  400535:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
  40053c:   eb 18                   jmp    400556 <func+0x29>
  40053e:   8b 45 fc                mov    -0x4(%rbp),%eax
  400541:   89 c6                   mov    %eax,%esi
  400543:   bf f4 05 40 00          mov    $0x4005f4,%edi
  400548:   b8 00 00 00 00          mov    $0x0,%eax
  40054d:   e8 be fe ff ff          callq  400410 <printf@plt>
  400552:   83 45 fc 01             addl   $0x1,-0x4(%rbp)
  400556:   83 7d fc 63             cmpl   $0x63,-0x4(%rbp)
  40055a:   7e e2                   jle    40053e <func+0x11>
  40055c:   8b 45 fc                mov    -0x4(%rbp),%eax
  40055f:   c9                      leaveq 
  400560:   c3                      retq   

0000000000400561 <main>:
  400561:   55                      push   %rbp
  400562:   48 89 e5                mov    %rsp,%rbp
  400565:   e8 c3 ff ff ff          callq  40052d <func>
  40056a:   5d                      pop    %rbp
  40056b:   c3                      retq   
  40056c:   0f 1f 40 00             nopl   0x0(%rax)
0000000000 40052D:
40052d:55%推送rbp
40052e:48 89 e5 mov%rsp,%rbp
400531:48 83 ec 10子$0x10,%rsp
400535:c7 45 fc 00移动$0x0,-0x4(%rbp)
40053c:eb 18 jmp 400556
40053e:8b 45 fc mov-0x4(%rbp),%eax
400541:89 c6 mov%eax,%esi
400543:bf f4 05 40 00 mov$0x4005f4,%edi
400548:b8 00 mov$0x0,%eax
40054d:e8 fe ff ff callq 400410
400552:83 45 fc 01 addl$0x1,-0x4(%rbp)
400556:83 7d fc 63 cmpl$0x63,-0x4(%rbp)
40055a:7e e2 jle 40053e
40055c:8b 45 fc mov-0x4(%rbp),%eax
40055f:c9-Q
400560:c3 retq
0000000000400561 :
400561:55%按需付费
400562:48 89 e5 mov%rsp,%rbp
400565:e8 c3 ff ff ff callq 40052d
40056a:5d pop%rbp
40056b:c3 retq
40056c:0f 1f 40 00 nopl 0x0(%rax)

这里是一个带有
main
的小代码,它调用一个名为
func
的简单函数

我们可以使用
gcc main.c-S main.S
编译这个c代码。main.S应该是一个程序集输出

在程序集中,您可能会看到CPU指令:push、pop、leave、enter。这些指令负责堆栈帧管理

如果使用gcc和其他选项进行编译,您可能会注意到一些堆栈管理差异

#include <stdio.h>

int func(void);

int func(void)
{
    int i;

    for(i=0;i<100;i++)
        printf("%d",i);

    return i;
}

int main(void)
{
    return func();
}
这里函数
func
objdump main.o-S
).main.o的objdump输出是通过以下方式获得的:
gcc main.c-o main.o

000000000040052d <func>:
  40052d:   55                      push   %rbp
  40052e:   48 89 e5                mov    %rsp,%rbp
  400531:   48 83 ec 10             sub    $0x10,%rsp
  400535:   c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
  40053c:   eb 18                   jmp    400556 <func+0x29>
  40053e:   8b 45 fc                mov    -0x4(%rbp),%eax
  400541:   89 c6                   mov    %eax,%esi
  400543:   bf f4 05 40 00          mov    $0x4005f4,%edi
  400548:   b8 00 00 00 00          mov    $0x0,%eax
  40054d:   e8 be fe ff ff          callq  400410 <printf@plt>
  400552:   83 45 fc 01             addl   $0x1,-0x4(%rbp)
  400556:   83 7d fc 63             cmpl   $0x63,-0x4(%rbp)
  40055a:   7e e2                   jle    40053e <func+0x11>
  40055c:   8b 45 fc                mov    -0x4(%rbp),%eax
  40055f:   c9                      leaveq 
  400560:   c3                      retq   

0000000000400561 <main>:
  400561:   55                      push   %rbp
  400562:   48 89 e5                mov    %rsp,%rbp
  400565:   e8 c3 ff ff ff          callq  40052d <func>
  40056a:   5d                      pop    %rbp
  40056b:   c3                      retq   
  40056c:   0f 1f 40 00             nopl   0x0(%rax)
0000000000 40052D:
40052d:55%推送rbp
40052e:48 89 e5 mov%rsp,%rbp
400531:48 83 ec 10子$0x10,%rsp
400535:c7 45 fc 00移动$0x0,-0x4(%rbp)
40053c:eb 18 jmp 400556
40053e:8b 45