翻译《有关编程、重构及其他的终极问题?》——1. 别把编译器的事给做了

翻译《有关编程、重构及其他的终极问题?》——1.别把编译器的事给做了

标签(空格分隔): 翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
校验者:高国栋
最后更新:2016年11月12日


本书背景说明、总目录等介绍,可以跳转到以下链接进行查看:
http://blog.csdn.net/headman/article/details/53045891

欢迎大家转载,但请附上原作者以及翻译者的名字、原文出处,以尊重光荣的劳动者。


1.别把编译器的事情给做

考虑下面这段从MySQL项目里抽取出来的源代码。这段代码包含的错误被PVS-Studio分析诊断为:V525 The code containing the collection of similar blocks. Check items ‘0’,’1’,’2’,’3’,’4’,’1’,6’ in lines 680,682,689,691,693,695.(译者注:这段应该是PVS-Studio的分析输出,不翻译了,大家注意那个Check items后面4和6之间是1,而不是5,这个就是一个隐藏的错误)。

static int rr_cmp(uchar *a, uchar *b)
{
    if (a[0] != b[0])
        return (int)a[0] - (int)b[0];
    if (a[1] != b[1])
        return (int)a[1] - (int)b[1];
    if (a[2] != b[2])
        return (int)a[2] - (int)b[2];
    if (a[3] != b[3])
        return (int)a[3] - (int)b[3];
    if (a[4] != b[4])
        return (int)a[4] - (int)b[4];
    if (a[5] != b[5])
        return (int)a[1] - (int)b[5];       <<<<====
    if (a[6] != b[6]
        return (int)a[6] - (int)b[6];
    return (int)a[7] - (int)b[7];
}

解释
这是一个经典的错误,主要是因为拷贝粘帖代码段导致。很明显,这位程序员在拷贝粘帖代码段“return (int)a[1] - (int)b[1];”时,在改变数组下标时,忘了把a数组的下标“1”改成“5”。这就导致这个比较函数某些情况下会返回一个错误的值;这个错误一旦犯下,在后续是比较难被注意的。在我们用PVS-Studio扫描MySQL代码前,所有的测试都没有发现,所以这个问题是很难被检测到的。

正确的代码

if (a[5] != b[5])
    return (int)a[5] - (int)b[5];

建议
虽然上面的代码很整齐且易读,但它并不能阻止开发者忽略这个错误。当读到这样的代码时,因为你看到的代码都是类似的块,而且很难在每个块上都集中注意力,所以你几乎很难发现这个错误。

这样类似的代码块,看上去很像是这位程序员尽了最大的限度去主动优化后的结果,他把循环“给展开了”(译者注:有时展开循环能提高执行效率)。但我并不认为在这里是一个好主意。

首先,我怀疑这位程序员是否实现了其主动优化执行效率的目的。现代的编译器非常聪明,如果发现可以提高代码的执行效率,它就非常擅长自动把循环展开,而不需要你自己手工这么做。

其次,因为尝试优化代码而导致这个bug,但如果你些一个简单的循环,那么这个错误发生的机会就小的多。

我的建议是把以上函数写成如下形式:

static int rr_cmp(uchar *a, uchar *b)
{
    for (size_t i = 0; i < 7; ++i)
    {
        if (a[i] != b[i])
            return a[i] - b[i];
    }

    return a[7] - b[7];
}

好处:

  • 这个函数很容易阅读和理解。
  • 你大大降低了发犯错的机会。

我非常确信,这个函数不会比前面那个有错误的执行起来慢,因为现代的编译器会进行展开优化。

所以,我的建议是——写简单且易读的代码。这里有个规则:简单的代码通常就是正确的代码。不要尝试去做编译器的活——比如去展开循环。编译器无须你的帮助,就可以把绝大多数事情做好。这样的人工优化工作一般只有在少数特定极端的代码段才有效,特别是只有在确认这段代码执行真有的有问题(慢)的情况。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值