文字列リテラルが格納される正確な場所は、個々の実装に大きく依存します。唯一の要件は、リテラルがプログラム全体から見えることと、プログラムの開始時に割り当てられ、プログラムが終了するまで保持されることです。
プラットフォームによっては、リテラルを別のメモリ セグメント ( など.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 ....
文字列リテラルは、アドレス 0x400ac0 (私のシステムのセグメントにあります) から始まる"Adam"
配列として格納されます。char
.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 にコピーします。