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