【问题标题】:printf in C doesn't occupy memory?C中的printf不占用内存?
【发布时间】:2012-06-27 13:00:59
【问题描述】:

printf 是否占用栈中的内存?

printf("Hello world");

"Hello world" 有固定地址吗?

请帮助我理解。

编辑:

我们为printf 传递的参数是否存储在本地指针变量中。 如果我使用数组来存储 50 个字符串文字,它会占用堆栈内存,但如果我使用 printf 它不会占用内存 - 这是我听到的。但是不知道printf怎么不把内存当成我们声明的数组。

请帮我理解!

【问题讨论】:

    标签: c


    【解决方案1】:

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

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

    【讨论】:

    • 请注意,虽然字符串不占用堆栈,但printf 一个函数调用,并且会相应地增大堆栈。
    • @WoodrowDouglass 我对此表示怀疑。 printf 本身驻留在库中,它也有静态持续时间。
    • 我不是说printf 的代码在堆栈上,我的意思是call 指令将返回地址推入堆栈,因此调用 的行为任何非内联函数都会增加堆栈。
    • @WoodrowDouglass 哦,好的。没错。
    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      以下面的程序为例:

      #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 box (i686) 上,我们得到以下机器码:

      1 .文件“系统调用.c” 2.版本“01.01” 3 gcc2_compiled.: 4 .section .rodata 5 .LC0: 6 .string "你好,世界\n" 7.文本 8 .对齐 4 9 .globl 主要 10 .type main,@function 11 主要: 12 推升 %ebp 13 移动 %esp, %ebp 14 美元 8 美元,%esp 15 美元 12 美元,%esp 16 推力 $.LC0 17 调用 printf 18 加 16 美元,%esp 19 移动 $0, %eax 20 离开 21 退休 22.Lfe1: 23 .size main,.Lfe1-main 24 .ident“GCC:(GNU)2.96 20000731(红帽 Linux 7.2 2.96-112.7.2)”

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

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

      1 .文件“系统调用.c” 2 .section .rodata 3 .LC0: 4 .string "你好,世界" 5.文本 6 .globl 主要 7 .type main, @function 8个主要: 9.LFB2: 10 pushq %rbp 11 .LCFI0: 12 movq %rsp, %rbp 13.LCFI1: 14 movl $.LC0, %edi 15个看涨期权 16 移动 $0, %eax 17 离开 18 点 ;; ;;不包括附加内容 ;;

      在这种情况下,第 14 行将字符串文字的地址写入 寄存器 (%edi),而不是将其压入堆栈。还要注意,这个版本的 gcc 足够聪明,可以意识到由于我传递了一个 char * 类型的参数,它可以替代对 puts 的调用。

      无论哪种情况,您在调用时都会创建一个新的堆栈帧;不同之处在于堆栈帧中的内容。在 Red Hat 盒子上,它将包含字符串文字的地址;在 SLES 10 盒子上,它不会。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-20
        • 2017-11-16
        • 2017-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多