c goto动态label跳转
pg表达式引擎里面各个表达式的串联是使用goto动态label实现的。
// 定义部分 #if defined(EEO_USE_COMPUTED_GOTO) static const void *const dispatch_table[] = { &&CASE_EEOP_DONE, &&CASE_EEOP_INNER_FETCHSOME, &&CASE_EEOP_OUTER_FETCHSOME, &&CASE_EEOP_SCAN_FETCHSOME, &&CASE_EEOP_INNER_VAR, &&CASE_EEOP_OUTER_VAR, &&CASE_EEOP_SCAN_VAR, ... // 跳转 EEO_CASE(EEOP_OUTER_FETCHSOME) { CheckOpSlotCompatibility(op, outerslot); slot_getsomeattrs(outerslot, op->d.fetch.last_var); EEO_NEXT(); } // 宏定义 #define EEO_SWITCH() starteval: switch ((ExprEvalOp) op->opcode) #define EEO_CASE(name) case name: #define EEO_DISPATCH() goto starteval #define EEO_OPCODE(opcode) (opcode) #endif /* EEO_USE_COMPUTED_GOTO */ #define EEO_NEXT() \ do { \ op++; \ EEO_DISPATCH(); \ } while (0) #define EEO_JUMP(stepno) \ do { \ op = &state->steps[stepno]; \ EEO_DISPATCH(); \ } while (0)
也就是日常用的比较少的&&操作符。如下:
#include <stdio.h> #include <string.h> enum { ADD, SUB, MUL, DIV, END }; int main(int argc,char *argv[]) { static const void *const disptab[] = { &&L_ADD, &&L_SUB, &&L_MUL, &&L_DIV, &&L_END }; int code[] = {ADD,ADD,MUL,MUL,END}; int i = 0; int sum = 0; goto *disptab[code[i++]]; L_ADD: sum += 2; goto *disptab[code[i++]]; L_SUB: sum -= 2; goto *disptab[code[i++]]; L_MUL: sum *= 2; goto *disptab[code[i++]]; L_DIV: sum /= 2; goto *disptab[code[i++]]; L_END: printf("sum = %d\n",sum); return 0; }
其等价于switch case,如下:
for() { switch() { case ADD: sum += 2; break; case SUB: sum -= 2; break; case MUL: sum *= 2; break; case DIV: sum /= 2; break; case END: } }
相比来看,速度会更快。