我刚刚编译并反汇编了你的代码。inplace
并且inglobals
是相同的。这很直观:编译器可以将 const 字符串存储在.rodata
节中。
奇怪的是,gcc 产生了相当多的代码infunc
(见下文),可能是因为你“坚持”在s
堆栈上。定义s
asstatic
会产生与和infunc
相同的代码。inplace
inglobals
0000000000000010 :
10: 48 83 ec 18 sub $0x18,%rsp
14: 48 63 ff movslq %edi,%rdi
17: 64 48 8b 04 25 28 00 移动 %fs:0x28,%rax
1e: 00 00
20: 48 89 44 24 08 移动 %rax,0x8(%rsp)
25: 31 c0 xor %eax,%eax
27: c7 04 24 61 7a 53 00 移动 $0x537a61,(%rsp)
2e: 0f b6 04 3c movzbl (%rsp,%rdi,1),%eax
32: 48 8b 54 24 08 移动 0x8(%rsp),%rdx
37: 64 48 33 14 25 28 00 异或 %fs:0x28,%rdx
3e:00 00
40:75 05 jne 47
42: 48 83 c4 18 添加 $0x18,%rsp
46:c3 回复
47:e8 00 00 00 00 呼叫 4c
编辑
该位置%fs:0x28
与 GCC 的堆栈保护器有关。禁用它会给出以下代码:
0000000000000010 :
10: 48 63 ff movslq %edi,%rdi
13: c7 44 24 f0 61 7a 53 移动 $0x537a61,-0x10(%rsp)
1a: 00
1b: 0f b6 44 3c f0 movzbl -0x10(%rsp,%rdi,1),%eax
20:c3 重新调用
因此,在这种情况下,GCC 选择将您的字符串与代码内联存储,并在执行期间将其复制到堆栈中。我认为这是非常有效的,因为您的处理器的缓存已经充满了字符串,因此不会发生内存访问。
编辑
综上所述,三个版本都是等价的。然而,根据您的编译器实现,一个可能会比另一个更有效。对于 GCC,infunc
对于短字符串似乎更有效,因为字符串是与指令一起获取的。对于较大的字符串,我会使用inplace
or inglobals
。