c语言的If与Switch效率比较

Posted 雪靡

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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编译,在ReleaseX84环境下运行结果为:

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 ↩︎

以上是关于c语言的If与Switch效率比较的主要内容,如果未能解决你的问题,请参考以下文章

编程语言中IF语句与CASE语句的效率问题

C语言中if和switch有啥区别?

c++中for循环和switch语句哪个更高效

if-else与switch

C语言中的条件赋值语句和if——else语句执行效率比较,哪一个效率高些,坐等高手解惑

C语言 回滚技术 switch case