是否printf
占用堆栈中的内存?
printf("Hello world");
"Hello world"
有固定地址吗?
请帮我理解。
编辑:
我们为 传递的参数printf
是否存储在本地指针变量中。如果我使用数组来存储 50 个字符串文字,它会占用堆栈内存,但如果我使用printf
它,它不会占用内存 - 这就是我所听到的。但是我不知道怎么printf
不把内存作为我们声明的数组。
请帮我理解!
是否printf
占用堆栈中的内存?
printf("Hello world");
"Hello world"
有固定地址吗?
请帮我理解。
编辑:
我们为 传递的参数printf
是否存储在本地指针变量中。如果我使用数组来存储 50 个字符串文字,它会占用堆栈内存,但如果我使用printf
它,它不会占用内存 - 这就是我所听到的。但是我不知道怎么printf
不把内存作为我们声明的数组。
请帮我理解!
字符串字面量,这就是什么"Hello world"
,占用内存,但不在堆栈上,而是在只读静态段中。除了read-only memory
,其余的都是实现细节。
相同的字符串文字不必占用相同的内存(因此不能保证地址是恒定的),但它们可能会。
在 C 语言中,字符串文字具有静态存储持续时间。这意味着它们在整个程序期间都存在(并且指向它们的指针保持有效);这与通常在调用帧堆栈上实现的自动局部变量相反。
这取决于您平台的调用约定以及标准库的实现方式。
例如,采取以下程序:
#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 盒子上,它不会。