c语言的If与Switch效率比较

最近看到文章1表示Switch比If慢,这里就来测试一下是否属实。

立刻打开VS,编写以下代码:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAX_LOOP 100000000
int nums[5];
void switchFunc()
{
	int i, r;
	srand((unsigned)time(NULL));
	for (i = 0; i < MAX_LOOP; i++)
	{
		r = rand() % 5;
		switch (r)
		{
		case 3:
			nums[3]++;
			break;
		case 1:
			nums[1]++;
			break;
		case 2:
			nums[2]++;
			break;
		case 0:
			nums[0]++;
			break;
		default:
			nums[4]++;
			break;
		}
	}
}

void ifFunc()
{
	int i, r;
	srand((unsigned)time(NULL));
	for (i = 0; i < MAX_LOOP; i++)
	{
		r = rand() % 5;
		if (r == 3)
			nums[3]++;
		else if (r == 1)
			nums[1]++;
		else if (r == 2)
			nums[2]++;
		else if (r == 0)
			nums[0]++;
		else
			nums[4]++;
	}
}

int main()
{
	clock_t start, finish, i;
	double if_time, switch_time, if_total_time = 0, switch_total_time = 0;
	int test_time = 10;
	printf("Start test.\n");
	printf(" \tswitch time\tif time\n");
	for (i = 0; i < test_time; i++)
	{
		memset(nums, 0, sizeof(nums));
		start = clock();
		switchFunc();
		finish = clock();
		switch_time = (double)1000.0 * (finish - start) / CLOCKS_PER_SEC;
		switch_total_time += switch_time;
		start = clock();
		ifFunc();
		finish = clock();
		if_time = (double)1000.0 * (finish - start) / CLOCKS_PER_SEC;
		if_total_time += if_time;
		printf("#%d\t%0.0fms\t\t%0.0fms\n", i + 1, switch_time, if_time);
	}
	printf("\n");
	printf("total\t%0.0fms\t\t%0.0fms\n", switch_total_time / test_time, if_total_time / test_time);
	return 0;
}

使用VS2022编译,在ReleaseX86环境下运行结果为:

Start test.
        switch time     if time
#1      3929ms          3673ms
#2      3590ms          3584ms
#3      3606ms          3587ms
#4      3604ms          3585ms
#5      3601ms          3589ms
#6      3589ms          3586ms
#7      3605ms          3584ms
#8      3596ms          3581ms
#9      3591ms          3592ms
#10     3605ms          3593ms

total   3632ms          3595ms

测试结果表明,switch确实比if慢。这个原因来自CPU 分支预测2
编译器根据case的数量和case值的稀疏程度来翻译switch语句,当case情况比较多(例如4个以上),并且值的范围跨度比较小时,就会使用跳转表。

在这里插入图片描述

构建的跳转表为

.text:00415A6C jpt_4159A7      dd offset $LN10_0       ; DATA XREF: _switchFunc+97↑r
.text:00415A6C                 dd offset $LN8          ; jump table for switch statement
.text:00415A6C                 dd offset $LN9_0
.text:00415A6C                 dd offset $LN7

增加了条件到0-9以后,swtich比if快。

修改后的代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define MAX_LOOP 100000000
int nums[10];
void switchFunc()
{
	int i, r;
	srand((unsigned)time(NULL));
	for (i = 0; i < MAX_LOOP; i++)
	{
		r = rand() % 10;
		switch (r)
		{
		case 8:
			nums[8]++;
			break;
		case 3:
			nums[3]++;
			break;
		case 7:
			nums[7]++;
			break;
		case 1:
			nums[1]++;
			break;
		case 4:
			nums[4]++;
			break;
		case 2:
			nums[2]++;
			break;
		case 0:
			nums[0]++;
			break;
		case 6:
			nums[6]++;
			break;
		case 5:
			nums[5]++;
			break;
		default:
			nums[9]++;
			break;
		}
	}
}

void ifFunc()
{
	int i, r;
	srand((unsigned)time(NULL));
	for (i = 0; i < MAX_LOOP; i++)
	{
		r = rand() % 10;
		if (r == 8)
			nums[8]++;
		else if (r == 3)
			nums[3]++;
		else if (r == 7)
			nums[7]++;
		else if (r == 1)
			nums[1]++;
		else if (r == 4)
			nums[4]++;
		else if (r == 2)
			nums[2]++;
		else if (r == 0)
			nums[0]++;
		else if (r == 6)
			nums[6]++;
		else if (r == 5)
			nums[5]++;
		else
			nums[9]++;
	}
}

int main()
{
	clock_t start, finish, i;
	double if_time, switch_time, if_total_time = 0, switch_total_time = 0;
	int test_time = 10;
	printf("Start test.\n");
	printf(" \tswitch time\tif time\n");
	for (i = 0; i < test_time; i++)
	{
		memset(nums, 0, sizeof(nums));
		start = clock();
		switchFunc();
		finish = clock();
		switch_time = (double)1000.0 * (finish - start) / CLOCKS_PER_SEC;
		switch_total_time += switch_time;
		start = clock();
		ifFunc();
		finish = clock();
		if_time = (double)1000.0 * (finish - start) / CLOCKS_PER_SEC;
		if_total_time += if_time;
		printf("#%d\t%0.0fms\t\t%0.0fms\n", i + 1, switch_time, if_time);
	}
	printf("\n");
	printf("total\t%0.0fms\t\t%0.0fms\n", switch_total_time / test_time, if_total_time / test_time);
	return 0;
}

结果如下:

Start test.
        switch time     if time
#1      3962ms          3900ms
#2      3732ms          3787ms
#3      3750ms          3794ms
#4      3738ms          3794ms
#5      3727ms          3796ms
#6      3735ms          3785ms
#7      3729ms          3797ms
#8      3725ms          3799ms
#9      3744ms          3800ms
#10     3739ms          3784ms

total   3758ms          3804ms

结论

当条件分支比较少的情况下,if比较快,当条件分支比较多的情况下,swtich比较快。


  1. 为什么新一代的Rust、Go等编程语言都如此讨厌if-else、Switch结构 https://mp.weixin.qq.com/s?__biz=MjM5MjAwODM4MA==&mid=2650863132&idx=2&sn=8372881079ff08caaaab6402b701b472&chksm=bd5887cf8a2f0ed992ad407e346d14b1241f99d8e3247013be926821031d4ba0a4d9049955da&mpshare=1&scene=23&srcid=0817mTwF5NsGURzy0x2dGxQQ&sharer_sharetime=1629187233862&sharer_shareid=d3275e0a17ca4e2cadeabadfeb76ff9f#rd ↩︎

  2. 为什么很多程序员不用switch,而是大量的if else?|字节|代码|跳转|预测器_网易订阅 https://www.163.com/dy/article/G6H4B7RT05319WXB.html ↩︎

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值