printf
是否会占用堆栈中的内存?
printf("Hello world");
"Hello world"
是否有一个固定的地址?
请帮助我理解。
修改
我们为printf
传递的参数是否存储在本地指针变量中。
如果我使用一个数组存储50个字符串文字,它需要堆栈内存,但如果我使用printf
它不占用内存 - 就是我所听到的。但是我不知道printf
如何不像我们声明的数组那样占用内存。
请帮助我理解!
答案 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盒子上,它不会。