可以看到在O3优化下,编译器使用了寄存器来代替函数指针变量pf和循环变量i,但依然无法将fn1和fn2内联化。
下面看个稍复杂点的例子:
void fn1(){
}
void fn2(){
}
bool isFn2(void (*pf)(void)){
if(pf==&fn2) {
return true;
}
return false;
}
int main(){
void (*pf)(void);
for(int i=0;i<1000;i++) {
if(isFn2(pf)) {
pf=&fn1;
}else{
pf=&fn2;
}
(*pf)();
}
}
上面代码逻辑可以看到,将调用的函数指针变量pf到底是否指向fn1还是fn2取决于函数isFn2()的返回,isFn2()会根据当前的函数指针pf指向来来判断返回结果。
在O0优化下,下面可以很明了的看到其跳转逻辑:
00000000 <__Z3fn1v>: 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: c9 leave 4: c3 ret 00000005 <__Z3fn2v>: 5: 55 push %ebp 6: 89 e5 mov %esp,%ebp 8: c9 leave 9: c3 ret 0000000a <__Z5isFn2PFvvE>: a: 55 push %ebp b: 89 e5 mov %esp,%ebp d: 81 7d 08 05 00 00 00 cmpl $0x5,0x8(%ebp) 14: 75 04 jne 1a <__Z5isFn2PFvvE+0x10> 16: b0 01 mov $0x1,%al 18: eb 02 jmp 1c <__Z5isFn2PFvvE+0x12> 1a: b0 00 mov $0x0,%al 1c: c9 leave 1d: c3 ret 0000001e <_main>: 1e: 55 push %ebp 1f: 89 e5 mov %esp,%ebp 21: 83 e4 f0 and $0xfffffff0,%esp 24: 83 ec 20 sub $0x20,%esp 27: e8 00 00 00 00 call 2c <_main+0xe> 2c: c7 44 24 18 00 00 00 movl $0x0,0x18(%esp) 33: 00 34: eb 2c jmp 62 <_main+0x44> 36: 8b 44 24 1c mov 0x1c(%esp),%eax 3a: 89 04 24 mov %eax,(%esp) 3d: e8 c8 ff ff ff call a <__Z5isFn2PFvvE> 42: 84 c0 test %al,%al 44: 74 0a je 50 <_main+0x32> 46: c7 44 24 1c 00 00 00 movl $0x0,0x1c(%esp) 4d: 00 4e: eb 08 jmp 58 <_main+0x3a> 50: c7 44 24 1c 05 00 00 movl $0x5,0x1c(%esp) 57: 00 58: 8b 44 24 1c mov 0x1c(%esp),%eax 5c: ff d0 call *%eax 5e: ff 44 24 18 incl 0x18(%esp) 62: 81 7c 24 18 e7 03 00 cmpl $0x3e7,0x18(%esp) 69: 00 6a: 0f 9e c0 setle %al 6d: 84 c0 test %al,%al 6f: 75 c5 jne 36 <_main+0x18> 71: b8 00 00 00 00 mov $0x0,%eax 76: c9 leave 77: c3 ret
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-34432-3.html
靠分红成吗