0

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

printf("Hello world");

"Hello world"有固定地址吗?

请帮我理解。

编辑:

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

请帮我理解!

4

3 回答 3

5

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

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

于 2012-06-27T13:02:56.220 回答
3

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

于 2012-06-27T13:05:22.693 回答
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 .文件“系统调用.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被调用。

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

      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 盒子上,它不会。

于 2012-06-27T15:11:54.790 回答