C中的printf不占用内存?

时间:2012-06-27 13:01:00

标签: c

printf是否会占用堆栈中的内存?

printf("Hello world");

"Hello world"是否有一个固定的地址?

请帮助我理解。

修改

我们为printf传递的参数是否存储在本地指针变量中。 如果我使用一个数组存储50个字符串文字,它需要堆栈内存,但如果我使用printf它不占用内存 - 就是我所听到的。但是我不知道printf如何不像我们声明的数组那样占用内存。

请帮助我理解!

3 个答案:

答案 0 :(得分:5)

字符串文字,即"Hello world"所占用的内存,但不在堆栈中,而是在只读静态段中。除了read-only memory之外,其余的都是实现细节。

相同的字符串文字不必占用相同的内存(因此地址不保证是常量),但它们可能不会。

答案 1 :(得分:3)

在C语言中,字符串文字具有静态存储持续时间。这意味着它们在程序的整个持续时间内存在(并且指向它们的指针仍然有效);这与自动局部变量相反,后者通常在调用帧堆栈上实现。

答案 2 :(得分:1)

这取决于您的平台的调用约定以及标准库的实现方式。

例如,参加以下计划:

#include <stdio.h>

int main(void)
{
  printf("Hello, World\n");
  return 0;
}

以及以下命令行来编译它:

gcc -S -std=c99 -pedantic -Wall -Werror syscall.c

在使用gcc 2.96的32位Red Hat盒子(i686)上,我们得到以下机器代码:

      1         .file   "syscall.c"
      2         .version        "01.01"
      3 gcc2_compiled.:
      4                 .section        .rodata
      5 .LC0:
      6         .string "Hello, World\n"
      7 .text
      8         .align 4
      9 .globl main
     10         .type    main,@function
     11 main:
     12         pushl   %ebp
     13         movl    %esp, %ebp
     14         subl    $8, %esp
     15         subl    $12, %esp
     16         pushl   $.LC0
     17         call    printf
     18         addl    $16, %esp
     19         movl    $0, %eax
     20         leave
     21         ret
     22 .Lfe1:
     23         .size    main,.Lfe1-main
     24         .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)"

第16行将字符串文字的地址压入堆栈,然后调用printf

这是使用gcc 4.1.2在64位SLES 10盒(x86_64)上以相同方式编译的相同代码:


      1         .file   "syscall.c"
      2         .section        .rodata
      3 .LC0:
      4         .string "Hello, World"
      5         .text
      6 .globl main
      7         .type   main, @function
      8 main:
      9 .LFB2:
     10         pushq   %rbp
     11 .LCFI0:
     12         movq    %rsp, %rbp
     13 .LCFI1:
     14         movl    $.LC0, %edi
     15         call    puts
     16         movl    $0, %eax
     17         leave
     18         ret
;;
;; additional content not included
;;

在这种情况下,第14行将字符串文字的地址写入寄存器%edi),而不是将其推入堆栈。另请注意,此版本的gcc足够智能,可以实现,因为我传递了char *类型的单个参数,它可以替换对puts的调用。

在任何一种情况下,您在拨打电话时都会创建一个新的堆栈帧;不同之处在于堆栈框架中的内容。在Red Hat框中,它将包含字符串文字的地址;在SLES 10盒子上,它不会。