我试试下面的内容:
#include <bitset>
int main ()
{
std::bitset<32> bit32 { 0xf0f0f0f0 };
bit32[4].flip();
bit32[0] = 1;
}
使用GCC 4.8.1,我无法将其内联,objdump给了我更多或更少:
401536: c7 45 e4 f0 f0 f0 f0 movl $0xf0f0f0f0,-0x1c(%ebp)
40153d: 8d 45 e8 lea -0x18(%ebp),%eax
401540: c7 44 24 04 04 00 00 movl $0x4,0x4(%esp)
401547: 00
401548: 8d 55 e4 lea -0x1c(%ebp),%edx
40154b: 89 14 24 mov %edx,(%esp)
40154e: 89 c1 mov %eax,%ecx
401550: e8 93 13 00 00 call 4028e8 <__ZNSt6bitsetILj32EEixEj>
401555: 83 ec 08 sub $0x8,%esp
401558: 8d 45 e8 lea -0x18(%ebp),%eax
40155b: 89 c1 mov %eax,%ecx
40155d: e8 b2 12 00 00 call 402814 <__ZNSt6bitsetILj32EE9reference4flipEv>
401562: 8d 45 e8 lea -0x18(%ebp),%eax
401565: 89 c1 mov %eax,%ecx
401567: e8 10 13 00 00 call 40287c <__ZNSt6bitsetILj32EE9referenceD1Ev>
40156c: 8d 45 f0 lea -0x10(%ebp),%eax
40156f: c7 44 24 04 00 00 00 movl $0x0,0x4(%esp)
401576: 00
401577: 8d 55 e4 lea -0x1c(%ebp),%edx
40157a: 89 14 24 mov %edx,(%esp)
40157d: 89 c1 mov %eax,%ecx
40157f: e8 64 13 00 00 call 4028e8 <__ZNSt6bitsetILj32EEixEj>
401584: 83 ec 08 sub $0x8,%esp
401587: 8d 45 f0 lea -0x10(%ebp),%eax
40158a: c7 04 24 01 00 00 00 movl $0x1,(%esp)
401591: 89 c1 mov %eax,%ecx
401593: e8 f0 12 00 00 call 402888 <__ZNSt6bitsetILj32EE9referenceaSEb>
401598: 83 ec 04 sub $0x4,%esp
40159b: 8d 45 f0 lea -0x10(%ebp),%eax
40159e: 89 c1 mov %eax,%ecx
4015a0: e8 d7 12 00 00 call 40287c <__ZNSt6bitsetILj32EE9referenceD1Ev>
4015a5: b8 00 00 00 00 mov $0x0,%eax
4015aa: 8b 4d fc mov -0x4(%ebp),%ecx
-O1,-O2,-O3也没有帮助,它完全优化了代码。 无论如何我可以避免调用函数吗?
答案 0 :(得分:5)
在启用优化的情况下进行编译。当我使用g++ -std=c++11 -O3
和以下稍微修改过的代码进行编译时,它会输出非常优化的代码:
输入:
#include <bitset>
volatile unsigned long v;
int main ()
{
std::bitset<32> bit32 { 0xf0f0f0f0 };
bit32[4].flip();
bit32[0] = 1;
v = bit32.to_ulong();
}
编译器输出:
main:
.LFB958:
.cfi_startproc
movl $4042322145, %eax
movq %rax, v(%rip)
xorl %eax, %eax
ret
.cfi_endproc
我需要添加volatile
变量以防止G ++彻底优化它。它基本上将所有bitset
操作优化为单movl
条指令。
在下面应用@ GlennTeitelbaum的建议,我也进行了第二次测试。这个通过从volatile
初始化bitset
并从argc
返回计算值来消除main
变量:
#include <bitset>
int main ( int argc, char *argv[] )
{
std::bitset<32> bit32 = argc;
bit32[4].flip();
bit32[0] = 1;
return bit32.to_ulong();
}
这个生成了以下编译器输出(与上面相同的标志):
main:
.LFB958:
.cfi_startproc
movl %edi, %eax
xorl $16, %eax
orq $1, %rax
ret
请注意,当您不知道xorl
的实际初始化值时,它确实优化了最小数量的计算步骤(orl
后跟bitset
)在编译时。第三条指令(movl %edi, %eax
)只是将argc
从它到达的寄存器移动到将返回结果的寄存器。
答案 1 :(得分:2)
如果您担心调用函数,为什么要使用bitset?
怎么样
unsigned int bit32; // Assume int is 32 bits
bit32 = 0xf0f0f0f0;
bit32 ^= 16;
bit32 |= 1;