如何把函数中的一部分代码作为局部函数来返回,这是跟体系架构密切相关的。需要了解运行栈的格式,并使用一些汇编指令。还要防止编译器对代码做不可预测的优化。
无论如何从函数中返回局部函数是可能的。这个一个x86上的例子:
#include <stdio.h>
int getip()
{
__asm__(
"movl 4(%ebp), %eax\r\n"
);
}
#define GET_LOCAL_ENTRY \
__asm__( \
"call _getip\n" \
"add $5, %eax\n" \
"leave\n" \
"ret\n" \
"pushl %ebp\n" \
"movl %esp, %ebp\n" \
"subl $12, %esp\n" \
);
#define IN_FUNC(a) ((a)+0x100)
int func(volatile int a, volatile int b, int op)
{
switch(op) {
case IN_FUNC('/'):
GET_LOCAL_ENTRY;
case '/':
printf("%d/%d:\n", a, b);
return a/b;
case IN_FUNC('*'):
GET_LOCAL_ENTRY;
case '*':
printf("%d*%d:\n", a, b);
return a*b;
case IN_FUNC('-'):
GET_LOCAL_ENTRY;
case '-':
printf("%d-%d:\n", a, b);
return a-b;
case IN_FUNC('+'):
GET_LOCAL_ENTRY;
case '+':
printf("%d+%d:\n", a, b);
return a+b;
}
return op;
}
int (*fp)(int, int);
int main()
{
int a, b;
printf("%d\n", func(1000,250, '+'));
printf("%d\n", func(1000,250, '-'));
printf("%d\n", func(1000,250, '*'));
printf("%d\n", func(1000,250, '/'));
fp = (int (*)(int, int)) (func(0,0,IN_FUNC('+')));
printf("%d\n", (*fp)(1000, 250));
fp = (int (*)(int, int)) (func(0,0,IN_FUNC('-')));
printf("%d\n", (*fp)(1000, 250));
fp = (int (*)(int, int)) (func(0,0,IN_FUNC('*')));
printf("%d\n", (*fp)(1000, 250));
fp = (int (*)(int, int)) (func(0,0,IN_FUNC('/')));
printf("%d\n", (*fp)(1000, 250));
return 0;
}
汇编代码中的5,是add, leave,ret 3条指令的长度。12是为后面printf的3个参数保留的栈空间。
这是运行结果:
1000+250:
1250
1000-250:
750
1000*250:
250000
1000/250:
4
1000+250:
1250
1000-250:
750
1000*250:
250000
1000/250:
4
可见,用正常switch 或者返回的函数指针得到了一样的结果。
(注)
好像在GET_LOCAL_ENTRY的嵌入汇编前,加一句
__asm__( " "::"m"(a),"m"(b):"memory");
就可以去掉func()参数中的volatile修饰了。