吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4714|回复: 54
收起左侧

[调试逆向] c/c++里的if和switch的区别

  [复制链接]
TES286 发表于 2021-8-16 19:41

0x01 总叙

大家都知道, c/c++在需要分支判断时, 有两个方法, 也就是if和switch

通常, 授课教师会告诉我们, switch使用了优化算法, 比if更高效(至少我学的时候老师是这样说的), 并且很多大型项目中多分支判断也用switch

举个例, cpython里的ceval.c(也就是执行python字节码的地方), 就有个大switch结构

(已将case内部折叠)

1.png

那么, 这两个方式到底有什么区别

0x02 测试

社么东西都要自己试试才好, 这里写两段c++代码, 如下

// if.cpp
# include <random>

int main()
{
    std::uniform_int_distribution<int> d(0, 5);
    std::random_device rd;
    int num = d(rd);
    if(num == 0)
    {
        return 0;
    }
    else if(num == 1)
    {
        return 1;
    }
    else if(num == 2)
    {
        return 2;
    }
    else if(num == 3)
    {
        return 3;
    }
    else if(num == 4)
    {
        return 4;
    }
    else if(num == 5)
    {
        return 5;
    }
}
// switch.cpp
# include <random>

int main()
{
    std::uniform_int_distribution<int> d(0, 5);
    std::random_device rd;
    int num = d(rd);
    switch(num)
    {
        case 0:
        {
            return 0;
            break;
        }
        case 1:
        {
            return 1;
            break;
        }
        case 2:
        {
            return 2;
            break;
        }
        case 3:
        {
            return 3;
            break;
        }
        case 4:
        {
            return 4;
            break;
        }
        case 5:
        {
            return 5;
            break;
        }
    }
}

这两段代码是否有区别? 试试才知道

给大家实验机器的配置

windows机器: Windows11, Intel Core i3-4170, msvc:19.29.30040, gcc:version 6.3.0 (MinGW.org GCC-6.3.0-1)

linux机器: Ubuntu21.04, arm64, respiberry 4 mode B, gcc:version 10.3.0 (Ubuntu 10.3.0-1ubuntu1~20.10)

我们使用以下命令编译

windows:

cl if.cpp
cl switch.cpp

linux:

g++ if.cpp -o if
g++ switch.cpp -o switch

使用该python脚本记录时间

import time
import os

def get_time(command):
  t1 = time.time()
  os.system(command)
  t2 = time.time()
  return t2 - t1

time_list_if = list()
time_list_switch = list()

# 使用if
for i in range(5):
  time_list_if += [get_time('./if')]

# 使用switch
for i in range(5):
  time_list_switch += [get_time('./switch')]

print('使用if判断的耗时')
print(time_list_if)
print('使用switch判断的耗时')
print(time_list_switch)

测试结果

Windows:

2.png

linux:

3.png

虽然相差不是很大, 但明显, switch胜过if

这里只有5个分支,但是如果分支足够多, 那差别就会扩大

那么, 为什么会发生这种情况呢

0x03 分析二进制

仅在windows平台测试

使用以下方法编译代码到汇编

g++ -S if.cpp

g++ -S switch.cpp

将得到的两个.s文件进行diff

找到关键区域(两个文件因为地址和变量问题, 有很多无用的差异)

4.png

左:使用if,右:使用switch

可以看到, 使用switch之前还有一些操作, 但是每次判断少了一个cmpl, jne操作, 因此, 分支越多, switch和if的速度差就越来越大

这就是switch优化的关键点

0x04 其他

本教程所涉及的代码请到这里下载

下载:https://tes286.lanzoui.com/iMFC7spxeej 密码:0x11E

另外, 大家遇到不懂得问题可以自己动手去尝试, 自己经过尝试得到的结果比任何教程, 博客等等都有用

免费评分

参与人数 15威望 +1 吾爱币 +34 热心值 +13 收起 理由
Nests + 1 + 1 用心讨论,共获提升!
SinonAX + 1 + 1 我很赞同!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
dsp2002 + 1 + 1 我很赞同!
莫千秋 + 1 用心讨论,共获提升!
574 + 1 + 1 用心讨论,共获提升!
挑灯看花 + 1 我很赞同!
wuaiwu77 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
collinslan + 1 + 1 赞!
laughtosky0 + 1 + 1 谢谢@Thanks!
小菜鸟一枚 + 1 + 1 学习了
woshicp + 1 + 1 热心回复!
三滑稽甲苯 + 2 + 1 用心讨论,共获提升!
tlf + 1 谢谢@Thanks!
塞北的雪 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

无名氏wyw 发表于 2021-8-16 23:04
开了O2之后,你能想到的常数优化基本都有了,真当编译器的开发人员没普通人聪明?

O0这东西存在的意义估计就是让某些专业的学生探究下编译原理吧(
涛之雨 发表于 2021-8-16 21:28
emmm编译难道会不一样么?
记得之前有看到switch编译后变成通过eax跳转
就只有一行 jmp [eax](类似的语句)
就实现了分支跳转,
而if就只能一个个的判断
alanyelan 发表于 2021-8-16 22:23
其实从if和switch 两个单词的含义来看,if就没有switch快。
塞北的雪 发表于 2021-8-16 19:51
switch L7那里没看明白,他应该是比较值后直接跳转对应的label吧,但是.long是什么东西???
 楼主| TES286 发表于 2021-8-16 20:15
塞北的雪 发表于 2021-8-16 19:51
switch L7那里没看明白,他应该是比较值后直接跳转对应的label吧,但是.long是什么东西???

long应该是数据类型

一般c/c++中int的类型好像在底层就是long类型
头像被屏蔽
tlf 发表于 2021-8-16 20:30
提示: 作者被禁止或删除 内容自动屏蔽
hswei 发表于 2021-8-16 20:45
先收藏了,仔细理解
三滑稽甲苯 发表于 2021-8-16 21:01
一直只是听说switch快,也不知道为什么,感谢lz的深入分析~
拜拜系 发表于 2021-8-16 22:58
看来switch会比较好用,待我细细品一下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-3-29 21:25

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表