字符串文字的确切存储位置很大程度上取决于个人实现;唯一的要求是文字对整个程序可见,并且在程序启动时分配并保持到程序终止。
某些平台可能会将文字存储在不同的内存段(例如.rodata
)中。
至于区别
char *name = "Adam";
和
char name2[] = "Adam";
图片可能会有所帮助。以下是我的特定系统上的情况:
Item Address 00 01 02 03
---- ------- -- -- -- --
"Adam" 0x400ac0 41 64 61 6d Adam
0x400ac4 00 22 41 64 ."Ad
name 0x7fff39dbdb78 c0 0a 40 00 ..@.
0x7fff39dbdb7c 00 00 00 00 ....
name2 0x7fff39dbdb70 41 64 61 6d Adam
0x7fff39dbdb74 00 7f 00 00 ....
字符串文字"Adam"
存储为char
从地址 0x400ac0 开始的数组(位于.rodata
我系统的段中)。
该变量name
是一个指向char
并包含字符串文字地址的指针(我的系统是小端,所以地址读取“向后”)。
该变量name2
是一个数组,char
其内容是从字符串文字 中复制的。
编辑
可能更有帮助的是查看生成的机器代码。采取以下程序:
#include <stdio.h>
int main( void )
{
char *name = "Adam";
char name2[] = "Adam";
printf("name = %s, name2 = %s\n", name, name2 );
return 0;
}
我在 SLES 10 系统上编译它,gcc
如下所示:
gcc -o name2 -std=c99 -pedantic -Wall -Werror name2.c -Wa,-aldh=name2.lst
这在 name2.lst 中给了我以下汇编器输出:
GAS LISTING /tmp/ccuuqqGI.s page 1
1 .file "name2.c"
2 .section .rodata
3 .LC0:
4 0000 4164616D .string "Adam"
4 00
5 .LC1:
6 0005 6E616D65 .string "name = %s, name2 = %s\n"
6 203D2025
6 732C206E
6 616D6532
6 203D2025
7 .text
8 .globl main
10 main:
11 .LFB2:
12 0000 55 pushq %rbp
13 .LCFI0:
14 0001 4889E5 movq %rsp, %rbp
15 .LCFI1:
16 0004 4883EC10 subq $16, %rsp
17 .LCFI2:
18 0008 48C745F8 movq $.LC0, -8(%rbp)
18 00000000
19 0010 8B050000 movl .LC0(%rip), %eax
19 0000
20 0016 8945F0 movl %eax, -16(%rbp)
21 0019 0FB60500 movzbl .LC0+4(%rip), %eax
21 000000
22 0020 8845F4 movb %al, -12(%rbp)
23 0023 488D55F0 leaq -16(%rbp), %rdx
24 0027 488B75F8 movq -8(%rbp), %rsi
25 002b BF000000 movl $.LC1, %edi
25 00
26 0030 B8000000 movl $0, %eax
26 00
27 0035 E8000000 call printf
27 00
28 003a B8000000 movl $0, %eax
28 00
29 003f C9 leave
30 0040 C3 ret
31 .LFE2:
如您所见,字符串文字"Adam"
和"name = %s, name2 = %s\n"
存储在.rodata
节中(用于只读数据项)。第 18 行将字符串文字的地址复制到name
,而第 19 到 22 行将字符串文字的内容复制到 name2。