字符串文字的确切存储位置很大程度上取决于个人实现;唯一的要求是文字对整个程序可见,并且在程序启动时分配并保持到程序终止。
某些平台可能会将文字存储在不同的内存段(例如.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。