编程论坛's Archiver

nicholaslee 发表于 2008-7-3 15:55

switch语句问题

switch语句到底怎么用 [tk09]

卧龙孔明 发表于 2008-7-3 15:58

看书

sente 发表于 2008-7-3 17:28

Orz......同2#

nicholaslee 发表于 2008-7-3 19:51

额 伤心了 不管怎么样顶下

独孤小梦 发表于 2008-7-3 20:19

………………就是分支选择的语句!看书就明白了!
这个问题我回答得上!
回答完毕!

flyue 发表于 2008-7-3 20:20

不要伤心啊,2#说的绝对是正确地

nicholaslee 发表于 2008-7-3 20:37

额 初学者 部分东西还没能完全理解
  有什么好经验介绍下

独孤小梦 发表于 2008-7-3 20:40

…………一般C下的switch不是很常用!而且功能也没有别的大,你只需要了解一下就OK了!
一般使用别的来代替!

中学者 发表于 2008-7-3 20:41

用好switch也不容易,反正我不常用 - -

StarWing83 发表于 2008-7-4 08:54

[quote][bo][un]独孤小梦[/un] 在 2008-7-3 20:40 的发言:[/bo]

…………一般C下的switch不是很常用!而且功能也没有别的大,你只需要了解一下就OK了!
一般使用别的来代替! [/quote]

看看这份代码,会改变你对switch的认识:
register n = (count + 7) / 8; /* count > 0 assumed */
switch (count % 8)
{
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
    } while (--n > 0);
}

switch本质上,是对连续if判断常数的汇编级别的优化,通过使用“跳转表”代替不连续的级联跳转,提高代码效率。

因为现在OO思想的泛滥,所以大家可能觉得switch功能很弱,但是注意这么一个问题,只有与常数比较,才能使用跳转表的方式进行优化,而如果是一个对象(比如string),因为其比较本质上是一个子程序,所以无法应用这种优化方式,没有提供这种switch正是C的思想的体现。

卧龙孔明 发表于 2008-7-4 09:03

[quote][bo][un]StarWing83[/un] 在 2008-7-4 08:54 的发言:[/bo]



看看这份代码,会改变你对switch的认识:
register n = (count + 7) / 8; /* count > 0 assumed */
switch (count % 8)
{
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
c ... [/quote]

这段代码速率比for(i=0;i<count;i++) *to=*from++; 快吧?

StarWing83 发表于 2008-7-4 09:05

快一点儿,但主要用来体现switch的功能,这个代码叫做达夫设备(Duff’s Device)。

卧龙孔明 发表于 2008-7-4 09:09

[quote][bo][un]StarWing83[/un] 在 2008-7-4 09:05 的发言:[/bo]

快一点儿,但主要用来体现switch的功能,这个代码叫做达夫设备(Duff’s Device)。 [/quote]
但我感觉这个速率的提高不是因为switch,而是少了计数变量的计算
例如for(i=0;i<5;i++) x++; 就慢于++x++,++x++,++x;

[[it] 本帖最后由 卧龙孔明 于 2008-7-4 09:11 编辑 [/it]]

StarWing83 发表于 2008-7-4 09:11

http://blogs.sun.com/weixue/entry/duff_s_device_%E8%BE%BE%E5%A4%AB%E8%AE%BE%E5%A4%87

自己看

达夫设备是一个加速循环语句的C编码技巧。其基本思想是--减少循环测试的执行次数。

如果在一个for 循环中,其中操作执行得如果足够快(比如说,一个赋值)——那么测试循环条件占用了循环所用时间的很大部分。循环应该被部分解开,这样数个操作一次完成,测试操作也做的较少。[bo]其实,是通过switch语句将要进行的连续循环操作的次数进行了预判(根据擦case语句的位置)然后依次执行,而不必每次都去进行测试条件。[/bo]
在这里Duff's Device是个新颖的,有创造力的解决方案。这里有一个使用该模型的一个实例:快速拷贝和填充。

卧龙孔明 发表于 2008-7-4 09:15

看了,我说的没错啊,就是减少了判断

StarWing83 发表于 2008-7-4 09:16

你后句是对的,但是前一句是“不是因为switch”,很抱歉,减少判断的功臣就是switch。

卧龙孔明 发表于 2008-7-4 09:18

[quote][bo][un]StarWing83[/un] 在 2008-7-4 09:16 的发言:[/bo]

你后句是对的,但是前一句是“不是因为switch”,很抱歉,减少判断的功臣就是switch。 [/quote]


lingluoz 发表于 2008-7-4 11:30

fall through哦 8过好像这样会爆warning的

lingluoz 发表于 2008-7-4 11:42

额。。竟然不会报warning的搞。失误了
恩。。最简单的switch的例子就是
int a;
switch(a) {
case 1:
    puts("the number is 1");
    break;
case 2:
    puts("the number is 2");
    break;
default:
    puts("the number is neither 1 or 2");
    break;
}

注意 在每个case的最后一行 都要有一个break;
否则会继续执行下一个case的语句。。
恩。。

RockCarry 发表于 2008-7-4 20:35

// 通常是这样
void fastcopy(BYTE *pdest, BYTE *psrc, long count)
{
    int n;

    n = count / 8;
    do
    {
        *pdest++ = *psrc++;
        *pdest++ = *psrc++;
        *pdest++ = *psrc++;
        *pdest++ = *psrc++;
        *pdest++ = *psrc++;
        *pdest++ = *psrc++;
        *pdest++ = *psrc++;
        *pdest++ = *psrc++;
    } while (--n > 0);

    n = count % 8;
    do { *pdest++ = *psrc++; } while (--n > 0);
}

// 然而这样更快,也更新颖
// 只是大家没有能够理解而已
void fastcopy(BYTE *pdest, BYTE *psrc, long count)
{
    int n;

    n = (count + 7) / 8;
    switch (count % 8)
    {
    case 0: do { *pdest++ = *psrc++;
    case 7:      *pdest++ = *psrc++;
    case 6:      *pdest++ = *psrc++;
    case 5:      *pdest++ = *psrc++;
    case 4:      *pdest++ = *psrc++;
    case 3:      *pdest++ = *psrc++;
    case 2:      *pdest++ = *psrc++;
    case 1:      *pdest++ = *psrc++;
               } while (--n > 0);
    }
}

的确是一个很别致的代码,大家认真体会就是了。剩余数据的拷贝在第一次 do-while 循环中被执行,以后的循环中,每次循环都是拷贝了 8 个字节。switch 语句根据 count % 8 来转到相应位置,而转到的位置执行到 while 一句时,则是刚好将剩余数据拷贝完毕。这样做巧妙的减少了剩余数据拷贝时,所做的循环判断,因此其效率会比上面的算法快,然而这样的性能提升其实是微不足道的,而且这样的代码也不适合用于工程上。更加关键的是,这段代码的实际效率很大程度的依赖于编译器对 switch 语句的编译和优化处理。

所谓 Duff's Device 说的也就是这个意思。

页: [1] 2 3

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.