2

我在互联网上找到了一段代码,它的目标非常简单,但它使用了一种丑陋的方法。假设,作者正在使用 switch case 来确定先前定义的 Enum 的一些(非连续)值是否属于它们的范围。如果是,则函数返回true,仅此而已。否则,它返回false.

它实际上看起来像这样:

switch(value) {
case ONE:
case TWO:
/* many similar lines later */
case TWENTY:
case TWENTY_FIVE:
/* an afternoon later */
case ONE_HUNDRED:
    return true;
default:
    return false;
}

由于编译器生成的跳转表,他们使用 switch case 是合理的(即使跳转表不一定意味着从我收集的内容中即时查找)。即便如此,这也会产生无数不必要的代码行。

我已经阅读了有关函数内联和使用函数指针数组的信息,但我不知道如何在这种特定情况下使用它。

我如何避免用这样一个简单的案例(没有双关语)写很多case X:

4

3 回答 3

8

基于某个绑定整数有效地计算布尔值是位旋转的工作:

const unsigned long long ps[2] = {0x28208a20a08a28ac, 0x800228a202088288};

bool is_prime(unsigned x)
{
    return (x < 128) && ((ps[x >> 6] >> (x & 63)) & 1);
}

如果查看存储在数组中的数字的二进制表示,1 位表示素数,0 位表示复合数:

   2    8    2    0    8    a    2    0    a    0    8    a    2    8    a    c
0010 1000 0010 0000 1000 1010 0010 0000 1010 0000 1000 1010 0010 1000 1010 1100
    59             47     41           31        23     17      11      5   2
 61        53           43     37        29           19     13       7    3

要将其扩展到超过 128 个数字,只需增加数组大小并将<比较修补到is_prime. 常数 6 和 63 源于unsigned long long.

于 2016-02-29T19:34:29.420 回答
2

在 C/C++ 中避免重复和简单的 switch case?

是的,请避免这种情况。您通常应该在任何给定的域/上下文中以最高抽象级别工作,无论是编译时多态性(例如使用模板)、面向对象编程还是更简单的控制结构。首先正确性,代码清晰性和效率,然后是优化(并且只有在适当的测量之后)

在这种特殊情况下,您可以简单地这样做:

return (value < 100);

我不明白为什么 100 多行 switch 语句更好..即使它更快(这只是在没有实际测量的情况下的假设)它只会稍微快一点,所以它值得这么大惊小怪吗?不,或者至少在大多数现实生活场景中没有。如果应用程序如此关键,那么优化此类代码最好用汇编语言完成。

至于函数内联和函数指针数组-我不确定我是否理解问题所在,但是,如果您不了解如何使用这些功能进行优化,请不要使用它们.. 让编译器而是优化您的代码。

于 2016-02-29T18:32:46.770 回答
0

由于您有一个奇数枚举,跳过值,您可以反转您的解决方案。但是您需要声明跳过的数字(如果它只跳过几个)。

if( value > ONE_HUNDRED || value < ONE )
{
    return false;
}
else
{
    switch(value)
    {
         case SKIPPED_FIRST:
         case SKIPPED_SECOND:
         {
             return false;
         }
         break;
         default:
         {
             return true;
         }
    }
}
于 2016-02-29T18:40:37.657 回答