《CSAPP》switch语句使用跳转表实现

5 篇文章 0 订阅

  switch语句特别有用,这种语句不仅提高了C代码的可读行, 而且通过使用一种成为跳转表(jump table)的数据结构使得实现更加高效。

  跳转表是一个数组,表项i是一个代码段的地址。程序代码用switch索引值来执行一个跳转表内的数据引用,确认跳转指令的目的。

 gcc编译器根据case的数量与case值的稀疏程度来翻译开关语句。 当case的数量比较多,并且case值稀疏比较小时, 才会使用跳转表。 否则使用普通跳转,相当与if-else。

 

switch_one.c:

/* not use jump table */
int switch_one(int x)
{
    int result = x;

    switch (x) {

    case 1:
    case 2:
    case 3:
        result += 10;
        break;

    case 4:
    case 5:
    case 6:
        result += 40;
        break;

    default:
        result = 0;      
    }

    return result;
}

 

switch_two.c:

/* use jump table */
int switch_two(int x)
{
    int result = x;

    switch (x) {

    case 1:
        result += 10;
        break;

    case 2:
        result += 10;
        break;

    case 3:
        result += 10;
        break;

    case 4:
        result += 20;
        break;

    case 5:
        result += 20;
        break;

    case 6:
        result += 20;
        break;

    default:
        result = 0;      
    }

    return result;
}

 

使用gcc进行编译,编译时通过加-S选项, 产生汇编代码:

 

gcc -O2 -S switch_one.c产生switch_one.s, 用文本编辑器查看:

    .file    "switch_one.c"
    .text
    .p2align 4,,15
.globl _switch_one
    .def    _switch_one;    .scl    2;    .type    32;    .endef
_switch_one:
    pushl    %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %edx
    cmpl    $1, %edx
    movl    %edx, %eax
    jl    L9
    cmpl    $3, %edx
    jle    L5
    cmpl    $6, %edx
    jg    L9
    popl    %ebp
    leal    20(%edx), %eax
    ret
    .p2align 4,,7
L5:
    popl    %ebp
    addl    $10, %eax
    ret
    .p2align 4,,7
L9:
    popl    %ebp
    xorl    %eax, %eax
    ret

 

gcc -O2 -S switch_two.c产生switch_two.s, 用文本编辑器查看:

    .file    "switch_two.c"
    .text
    .p2align 4,,15
.globl _switch_two
    .def    _switch_two;    .scl    2;    .type    32;    .endef
_switch_two:
    pushl    %ebp
    movl    %esp, %ebp
    movl    8(%ebp), %edx
    cmpl    $6, %edx
    ja    L9
    jmp    *L10(,%edx,4)
    .section .rdata,"dr"
    .align 4
L10:
    .long    L9
    .long    L5
    .long    L5
    .long    L5
    .long    L8
    .long    L8
    .long    L8
    .text
    .p2align 4,,7
L9:
    popl    %ebp
    xorl    %eax, %eax
    ret
    .p2align 4,,7
L8:
    popl    %ebp
    leal    20(%edx), %eax
    ret
    .p2align 4,,7
L5:
    popl    %ebp
    leal    10(%edx), %eax
    ret

 

观察:

swithc_two.s中的L10, L10是个地址数组。

 

小结:

switch_one未使用跳转表。

switch_one与switch_two的case数量相同, 因为switch_two的case值稀疏相对比较小,所以switch_two使用了跳转表。

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值