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:
    }
}

相比来看,速度会更快。

posted @ 2024-10-06 20:22  zhjh256  阅读(9)  评论(0编辑  收藏  举报