IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【汇编 C】switch为什么高效率?分支语句if else与switch -> 正文阅读

[C++知识库]【汇编 C】switch为什么高效率?分支语句if else与switch

目录

前言

什么是分支语句?

if else分支语句

? ? ? ? if else的几种写法

? ? ? ? 注意事项

? ? ? ? 底层刨析

switch分支语句

? ? ? ? switch语句的格式

? ? ? ? 注意事项

? ? ? ? default与break的功能

? ? ? ? 底层刨析

switch语句为什么高效?????????

? ? ? ? 实例测试

? ? ? ? 结论?

? ? ? ? 注意事项

总结

结语


前言

? ? ? ? 本文章使用到的工具是vs2010,建议使用VC++6,操作都一样。

什么是分支语句?

????????分支语句即进行一个选择,如果出现情况A则进行相应的操作;如果出现情况B则进行相应的操作,等等。

if else分支语句

? ? ? ? 我们也知道if是如果的意思,那么可以根据意思理解,比如:

? ? ? ? if(love == true)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 如果love是真不是假

? ? ? ? ? ? ? ? printf("这是真爱。\n");? ? ? ? ? ? // 那么就输出这是真爱

? ? ? ? else? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 否则(如果love不是真,是假的)

? ? ? ? ? ? ? ? printf("假的。\n");? ? ? ? ? ? ? ? ? ?// 那么就输出假的

? ? ? ? if else的几种写法

? ? ? ? 1)if(条件) 语句;

? ? ? ? 2)if(条件) { 语句;...}

? ? ? ? 3)if(条件1)?语句1;

? ? ? ? ? ? ? else? 语句2;

? ? ? ? 4)if(条件1) { 语句1;...}

? ? ? ? ? ? ? else { 语句2;...}

? ? ? ? 5)if(条件1) 语句1;

? ? ? ? ? ? ? else if(条件2) 语句2;

? ? ? ? ? ? ? else 语句3

? ? ? ? 6)if(条件1) { 语句1;...}

? ? ? ? ? ? ? else if(条件2) { 语句2;...}

? ? ? ? ? ? ? else { 语句3;...}

? ? ? ? 注意注意!!!

? ? ? ? 上面的写法并不是所有的,也并不是!只要if写大括号、else if就必须写大括号的!!!什么时候写大括号,什么时候不写呢?只有当语句只有一条的时候才可以省略不写大括号,如果一个if条件成立之后需要做很多语句,那就必须带大括号。

? ? ? ? 注意事项

? ? ? ? 1、可以只写if语句不写else语句,但是不能只写else语句。

? ? ? ? 2、else if可写可不写,如果写就必须有if语句。

? ? ? ? 底层刨析

? ? ? ? 测试代码:

#include <stdio.h>
#include <Windows.h>

int main()
{
    __asm mov eax,eax;            // 无用的代码,设置断点,产生汇编
    int x = 1;            
    if(x == 1)                    // 这里是判断,必须使用'==',因为'='在编程里是赋值
        printf("x = 1\n");
    else if (x > 1)
        printf("x > 1\n");
    else
        printf("x < 1\n");
    system("pause");              // 防止程序立即退出
    return 0;
}

? ? ? ? 首先我们来看运行结果:

? ? ? ? 没问题。

? ? ? ? Ctrl+alt+f7重新生成,?F5运行,ALT+8调出反汇编,如下:

? ? ? ? 我们先来看if(x==1) printf("x=1\n");对应的汇编:?

? ? ? ? cmp dword ptr [x],1:

? ? ? ? ? ? ? ? 将局部变量x中的值与1进行比较。

? ? ? ? jne main+46h(5813d6h):

? ? ? ? ? ? ? ? 如果前者(x)不等于后者(1)就跳转到5813d6这个地址,可以发现这个地址是else if,如果等于的话就继续往下执行

? ? ? ? mov esi,esp:

? ? ? ? ? ? ? ? 备份

? ? ? ? push offset...:

? ? ? ? ? ? ? ? 传递给printf函数参数。

? ? ? ? call dword ptr[__imp__printf()]:

? ? ? ? ? ? ? ? 调用printf函数?

? ? ? ? add esp,4:

? ? ? ? ? ? ? ? 一个参数,平栈加4

? ? ? ? cmp esi,esp:

? ? ? ? ? ? ? ? 比较二者的值

? ? ? ? call @ILT+300:

? ? ? ? ? ? ? ? 如果两者的值不相等,这个函数会报错,相等不会。

? ? ? ? jmp main+7Ch(54180Ch):

? ? ? ? ? ? ? ? 跳转到54180C这个地址。

? ? ? ? 上面的指令是整个if printf的流程。先判断,如果不相等就跳转到else if,如果相等就执行输出,并且到最后输出完了会跳转到整个if elseif else分支之外。

? ? ? ? else if(x>1) printf("x>1");?

? ? ? ? else?

? ? ? ? 以上便是if else的底层汇编,可以发现如果条件是'>'那么底层就会判断是否小于等于,以此类推,大家可以实验下。?

switch分支语句

? ? ? ? switch语句的格式

? ? ? ? switch(表达式)

? ? ? ? {

? ? ? ? ? ? ? ? case 常量表达式1:

? ? ? ? ? ? ? ? ? ? ? ? 语句;

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? case 常量表达式2:

? ? ? ? ? ? ? ? ? ? ? ? 语句;

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? ? ? ? ? ...

? ? ? ? ? ? ? ? default:

? ? ? ? ? ? ? ? ? ? ? ? 语句;

? ? ? ? ? ? ? ? ? ? ? ? break;

? ? ? ? }

? ? ? ? 注意事项

? ? ? ? 1、switch后边表达式的结果不能是浮点数!

? ? ? ? 2、case后的值不能一样,并且必须是常量,一般对应switch后面表达式的各种结果

? ? ? ? 3、default放在最后的时候可以不用写break;但是放在前面必须写

? ? ? ? 4、default不一定写在最后面,如果写在前面必须带break;

? ? ? ? default与break的功能

? ? ? ? default就是默认的意思,可以看到,我们switch语句中有很多case,case就相当于if(x == ?)这样的。default就相当于else语句,当case中的表达式都不成立就会执行default,如下:

#include <stdio.h>
#include <Windows.h>

int main()
{
	int x = 1;
    switch(x)
    {
    case 2:            // 如果x==2
        printf("x=2\n");
        break;
    case 3:            // 如果x==3
        printf("x=3\n");
        break;
    default:           // 如果x!=2 并且 x!=3
        printf("x!=2、x!=3\n");
        break;
    }

    system("pause");
	return 0;
}

? ? ? ? 结果:

? ??

? ? ? ? break是什么??

? ? ? ? 如果循环语句中假如break;那么他会跳出循环,那么当我们条件分支语句加上break;他也是会跳出的。

? ? ? ? 为什么最后一行的不需要加break?

? ? ? ? 因为最后一行的没有必要加,他再执行一步,分支语句就会退出了,所以没必要。

? ? ? ? 例如(不加的情况):

#include <stdio.h>
#include <Windows.h>

int main()
{
	int x = 1;
    switch(x)
    {
    case 1:            // 如果x==1
        printf("x=1\n");

    case 3:            // 如果x==3
        printf("x=3\n");
        break;
    default:           // 如果x!=2 并且 x!=3
        printf("x!=2、x!=3\n");

    }

    system("pause");
	return 0;
}

? ? ? ? 结果:

? ? ? ? 我们得到两点结论:

? ? ? ? 1、如果上面的条件成立了,但是没有写break,那么执行了语句之后还会继续往下执行不会退出分支语句

? ? ? ? 2、当上面的条件成立了之后如果没有写break,那么继续往下执行的时候就不会再判断case了,只有等到break;才会退出,或者一直执行完。?

? ? ? ? 底层刨析

? ? ? ? 代码:

#include <stdio.h>
#include <Windows.h>

int main()
{
	__asm mov eax,eax;
	int x = 1;
    switch(x)
    {
    case 2:            // 如果x==1
        printf("x=2\n");
		break;
    case 3:            // 如果x==3
        printf("x=3\n");
        break;
    default:           // 如果x!=2 并且 x!=3
        printf("x!=2、x!=3\n");
    }

    system("pause");
	return 0;
}

? ? ? ? __asm处断点、CTRL+ALT+F7重新生成、F5调试、ALT+8反汇编:

? ? ? ? 这里就不一步一步分析了。

?

?

? ? ? ? 可以看到switch语句也是判断,如果等于就跳转到对应的位置,和if else语句貌似是一样的,那么为什么说switch语句高效呢??

switch语句为什么高效?????????

? ? ? ? 首先我们需要了解一下switch语句的应用场景,我们知道游戏中一般都会有快捷键,这些快捷键的底层一般都是switch语句设计的,如果有快捷键,基本上不会只有一个快捷键。所以,如果仅仅是一两个条件,是根本看不出switch语句与if else的差距的。

? ? ? ? 我这里使用的是vs2010,在这个编译器中,当条件达到四个时(不含default),switch语句就会开始高效,他与if else的差距也能轻易看出来了。(并不是所有场景都是switch条件达到四个才开始高效,一般这与编译器优化有关)。

? ? ? ? 实例测试

? ? ? ? 示例代码if else四条件:

#include <stdio.h>
#include <Windows.h>

int main()
{
    __asm mov eax,eax;    // 此处设置断点
	int x = 1;

	if(x == 1)
		printf("x=1\n");
	else if(x == 2)
		printf("x=2\n");
	else if(x == 3)
		printf("x=3\n");
	else if(x == 4)
		printf("x=4\n");
	else
		printf("x!=1、2、3、4\n");

    system("pause");
	return 0;
}

? ? ? ? ctrl+alt+f7重新生成、F5调试、ALT+8反汇编:

? ? ? ? 可以看到if else语句条件多与少是没有区别的。

? ? ? ? 示例代码switch:

#include <stdio.h>
#include <Windows.h>

int main()
{
	__asm mov eax,eax;
	int x = 1;
	switch(x)
	{
	case 1:
		printf("1\n");
		break;
	case 2:
		printf("2\n");
		break;
	case 3:
		printf("3\n");
		break;
	case 4:
		printf("4\n");
		break;
	default:
		printf("x!=1、2、3、4\n");
	}

	system("pause");
	return 0;
}

?????????ctrl+alt+f7重新生成、F5调试、ALT+8反汇编:

? ? ? ? 直接看图:

? ? ? ? 结论?

? ? ? ? 当switch语句的条件超过一定个数时,底层会生成一张表(就是某个地址*edx+4我们查看所谓的某个地址就会看到这张表,如下

? ? ? ? 这张表是通过算法计算生成的,里边存放着所有case的成立之后跳转的地址,所以我们不需要再判断一次跳转一次,判断一次跳转一次......我们直接可以通过这张表,跳转到对应的位置,这也就是switch语句的精妙之处。当分支特别多的时候switch语句与if else的差距就会越来越大。?

? ? ? ? 注意事项

? ? ? ? 这里大家可以通过demo程序测试一下,如果是case 1:、case 3:、case 7:这样分隔开的话,底层会是什么样的呢?如果是case 1:、case 10:、case 100:这样差距特别大的,那么switch底层又会怎么办呢?跟谁比?减多少?

? ? ? ? 这样的问题很简单,写个程序测试一下一眼就能得出结论,所以我就不写了。

总结

? ? ? ? 无论是if else或是switch都各有应用场景,如果你觉得switch高效,那么以后什么地方都用switch吗?不能这样,因为很多地方不需要判断那么多次,并且switch不能像if else那么灵活。

?

结语

? ? ? ? 文章到这里就结束了,感谢大家观看!另外如果有错,还请一定指出;如果有听不懂,一定要问。?

? ? ? ? 封面:

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-25 23:05:06  更:2022-09-25 23:06:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 17:33:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码