コードをコンパイルして逆アセンブルしました。inplace
とinglobals
同一です。.rodata
これは非常に直感的です。コンパイラは const 文字列をセクションに格納できます。
奇妙なことに、gcc はinfunc
(以下を参照)に対して非常に多くのコードを生成s
します。s
asを定義すると、 and と同じコードstatic
が生成されます。infunc
inplace
inglobals
0000000000000010 :
10: 48 83 ec 18 サブ $0x18、%rsp
14: 48 63 ff movslq %edi,%rdi
17: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
1e: 00 00
20: 48 89 44 24 08 mov %rax,0x8(%rsp)
25: 31 c0 xor %eax,%eax
27: c7 04 24 61 7a 53 00 movl $0x537a61,(%rsp)
2e: 0f b6 04 3c movzbl (%rsp,%rdi,1),%eax
32: 48 8b 54 24 08 mov 0x8(%rsp),%rdx
37: 64 48 33 14 25 28 00 または %fs:0x28,%rdx
3e: 00 00
40: 75 05 年 47
42: 48 83 c4 18 追加 $0x18、%rsp
46: c3 retq
47: e8 00 00 00 00 callq 4c
編集
場所%fs:0x28
は、GCC のスタック プロテクターに関連しています。無効にすると、次のコードが得られます。
0000000000000010 :
10: 48 63 ff movslq %edi,%rdi
13: c7 44 24 f0 61 7a 53 movl $0x537a61,-0x10(%rsp)
1a:00
1b: 0f b6 44 3c f0 movzbl -0x10(%rsp,%rdi,1),%eax
20: c3 retq
したがって、この場合、GCC は文字列をコードとインラインで格納し、実行中にスタックにコピーすることを選択しました。プロセッサのキャッシュはすでに文字列で満たされているため、メモリアクセスは発生しないため、これは非常に効率的であると私は主張します。
編集
要約すると、3 つのバージョンはすべて同等です。それでも、コンパイラの実装によっては、一方が他方よりも効率的であることが判明する場合があります。GCC の場合infunc
、文字列は命令と共にフェッチされるため、短い文字列の方が効率的です。大きな文字列の場合は、inplace
orを使用しますinglobals
。