当前位置:C++技术网 > 资讯 > 双重取反!!的妙用以及条件判断if为什么效率很低

双重取反!!的妙用以及条件判断if为什么效率很低

更新时间:2015-06-25 21:21:28浏览次数:1+次

    在研究memcpy_s函数内部原理时,发现!!的用法,第一反应以为是多此一举,但是仔细一想,太有意思了。然后在一个C++群里面讨论一番,越发的清楚,群友们都很有兴趣,很有意思,我也是在讨论中额外的总结出来一些东西。因为原本只是稍微这么一想,但是群友们疑问比较多,为了讲清楚,所以就更加深入的想想,比如想想具体应用场景等,收获颇丰。这个妙用,还确实可以带来很多好处,比如可以替换掉条件判断,这样就优化了代码,提高了代码执行效率,也让代码更加整洁优美,还可以实现额外的功能。超棒!!
    双重取反最基本的理解:
    !是对布尔值进行取反,真则变假,假则变真。在C/C++中,非零即真,零则为假。那么就有一个问题,你传入的值只要不是0就是真,那么你如何让bool值只接受0或1,而不要接受其他数字呢?
    第一感觉,那就是对传入的值if判断,如果不等于0或者1,则赋值为1。这样确实是可以的,那么,此时代码写起来是不是这样的:

int i=5;
if(i!=0 && i!=1)i=1;
     那么此时,代码是不是比较长,比较复杂了。不仅如此,编译器编译成汇编代码时,就变成了跳转指令以及两条比较汇编指令,那么这么两句C语言代码,编程的汇编代码就长了很多,结构也复杂了。因为有跳转。
    为什么效率变低了呢?现在的计算机有一个局部性的原理的优化,就是按照指令执行顺序来执行,那么不用切换指令寄存器的值,挨个执行指令即可。但是有了跳转后,就要更换指令寄存器的值,那么跳转指令附近的指令就是不会执行的,因为会跳转到其他地方,从而不能顺序执行,在切换指令寄存器这一个过程中,就损失了效率,相对于原先顺序执行,效率大大降低。这是其中一个问题,另一个问题就是,这样的条件判断,多了判断的语句,条件越多,产生的指令越多,增加了指令必然相对的降低了效率。
    而使用双重取反来实现,代码如下: 
int i=5;
i = !!(i);
     这么一条赋值加双重取反,避免了条件判断带来的性能损失,且代码简短,产生的指令也少。并且取反异或等等操作对于CPU来说,执行效率是很高的。这样,在性能上大大提高了。代码也简洁优美了。代码也并不难懂,只是大家平常没有这么用而已。

    下面给个完整的代码来展示。代码如下:

enum E// - 定义枚举类型
{
    ZERO = 0,
    ONE = 1
};

void test(E e);// - 两种模式操作,不能有其他模式操作

void test(E e)
{
    E e_Temp = !!(e);// - 0以外的都处理成1,这里很轻松避开了if。
    swtich(e_Temp )
    {
        case ZERO :// - 执行功能代码0
            break;
        case ONE : // - 执行功能代码1
            break;
    }
}

//使用函数:

test(ZERO);// - 选择功能0
test(5);// - 选择功能1

    代码也都很简单,只是让大家有个整体的认识。当然,双重取反不限于使用在这个场景中。很多底层算法提高效率,都可以用上这个,从而避开了if。
    而代码中涉及到的枚举定义,请参考文章《宏、常量、枚举、结构体和共用体对比分析之枚举》,就不在这里重复了。