C语言switch中case仅仅只是一个标签

本文介绍了C语言中switch语句的特性,通过一个示例展示了case标签可以连续执行的效果,类似于goto。接着讲解了达夫设备(Duff's device)如何利用这一特性优化数据复制的效率,通过以8个数据为一组的方式减少判断次数,提高拷贝速度。相比于传统for循环,达夫设备在特定场景下能提供更高的性能。
摘要由CSDN通过智能技术生成

fe74d097bfaf49ced94b93d9c88128f0.gif

正文


大家好,我是bug菌~

最近在看一些开源的东西,发现switch中的case标识仅仅只是一个标签,跟使用goto语句所定义的label标签是类似的。

这样说可能大家还不是很好理解,下面给一个小例子了解一波:

1#include <stdio.h>
 2#include <stdlib.h>
 3
 4void Function(int statue)
 5{
 6    switch(statue)
 7    {
 8        case 0:
 9        {
10            printf("123");
11            case 1: //注意!!!
12            printf("456\n");
13
14        }break;
15        default:break;
16    }
17}
18
19int main(int argc, char *argv[]) {
20
21    Function(0);
22    Function(1);
23    return 0;
24}

按照我们平时的编程习惯和风格,case应该拥有自己的代码块才对,怎么在上面的代码中case 1放到了case 0中,能编译通过吗?

既然代码都写出来了,编译肯定是没有问题的,并且还能正确输出如下结果:

4e49d7f661bb620999c1fc52eaa4ea46.png

根据结果,也就说明当statue等于1的时候,switch会直接跳转到匹配的标签处,而不会管所谓的代码块。

所以前面也说了,有点goto的感觉了~

有朋友该说了,bug菌,这也太影响程序的可读性了吧,有问题bug都不好找~

确实,这样的做法在编码风格中算是摒弃的,但是也不能因为要注意编码风格而限制了我们对C语言编程的想象,比如下面这个有名的算法就利用了这点:

汤姆·达夫利用C语言switch语句这种特性优化了串行复制算法--达夫设备(英文:Duff's device)

我们平时要复制一块数据会使用如下编码实现:

1void  MyCopy( int * Dst, int * Src, int count)
2{
3    int i = 0;
4
5    for(i = 0;i != count; ++i) 
6    {
7      *Dst ++  = *Src ++ ;
8    } 
9}

应该够简单吧,那再看看达夫怎么处理的:

1void duff_Copy( int * to, int* from, int count)
 2 {
 3    int n = (count+7)/8;
 4
 5    switch( count%8 ) 
 6   {    
 7     case 0: do{ *to++ = *from++;
 8     case 7:     *to++ = *from++;
 9     case 6:     *to++ = *from++;
10     case 5:     *to++ = *from++;
11     case 4:     *to++ = *from++;
12     case 3:     *to++ = *from++;
13     case 2:     *to++ = *from++;
14     case 1:     *to++ = *from++;
15               }while(--n > 0);
16    }
17}

达夫设备进行数据复制,就是利用了switch会直接跳转到case标签处进行继续运行,如果没有break语句,继续执行下面的内容,直到while循环退出。

相比我们常用的数据拷贝MyCopy,每拷贝一个数据就要判断一次循环计数是否达到。

而达夫则以8个数据为一组(当然你可以设计得更多,不过太多在效率上就优化得不明显了),首先做了取余的处理,把不能成组的数据优先copy,然后判断一次循环截止条件,如果不满足,后续就一直是8个一组进行copy并进行循环截止判断,直到while循环退出,这样的拷贝效率当然比我们传统的for循环处理方式要高。

写到这里,bug菌在想,为什么这段代码不直接用汇编来写呢?因为功能上比较简单,用汇编实现也不是什么难事,并且能够根据平台的一些特性进行指令上的优化。

后来又想了想,可能一方面考虑到C语言相对可移植性会更好一点,另一方面或许达夫就是酷爱用C语言编程吧。

最后

      好了,今天就跟大家分享这么多了,如果你觉得有所收获,一定记得点个~

最后一个bug,bug菌唯一创作平台~

d0374629aaa768f84fa0f9fd7fa859b9.png

推荐专辑  点击蓝色字体即可跳转

☞  MCU进阶专辑 b0e59b66b3b903fc2f0d9ebbdbc1c102.gif

☞  嵌入式C语言进阶专辑 1a96857d38cba7cf8547bb24e06a25f9.gif

☞  “bug说”专辑 4e7d24e0f796a351bdb0b7dc57f8457c.gif

☞ 专辑|Linux应用程序编程大全

☞ 专辑|学点网络知识

☞ 专辑|手撕C语言

☞ 专辑|手撕C++语言

☞ 专辑|经验分享

☞ 专辑|电能控制技术

☞ 专辑 | 从单片机到Linux

97f1d09ce699aadbfaa5d0ee408ce01b.gif

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值