C++小知识:不要去做编译器的工作

 更新时间:2019年01月16日 15:32:11   作者:修语讲编程  
今天小编就为大家分享一篇关于C++小知识:不要去做编译器的工作,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

对于C++编程的老鸟来说,有时候他们喜欢把一些东西按照编译器的工作原理进行改写,以便提高代码的运行效率。这么做确实高明,也能体现出程序员的水平,但是这么做也是有风险的。因为有时候你可能会因为一些简单的笔误,而造成非常难以察觉的错误。本文就给出了类似的例子。

这个Bug 出现在MySQL源代码中。

错误代码:

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];
}

说明:

这是一个在对代码段进行拷贝粘贴时出现的典型错误。程序员很可能是把“if (a[1] != b[1]) (int) a[1] – (int) b[1];” 这段代码拷贝了好几遍(然后手动改数组下标),用来实现一个循环。不过程序员忘记把其中某一行的数组下标 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];
}

这种写法有两个优势:

  • 1.这个函数更容易阅读和理解。
  • 2.编写代码时,降低犯错几率。

至于性能方面,我敢说这个版本不会比之前写得很长的那个版本慢。

这个推荐的方法实际上表达了下面的意思:代码要简单易读。简单的代码通常即是正确的代码。不要去做编译器的工作——例如,(手动)展开循环。编译器很明确知道自己该做什么,并不需要你的帮助。手动代码优化工作只针对某些特定的关键代码,而且只在分析器已经确认这些代码是瓶颈以后,才可能恰当。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • C++将音频PCM数据封装成wav文件的方法

    C++将音频PCM数据封装成wav文件的方法

    这篇文章主要为大家详细介绍了C++将音频PCM数据封装成wav文件的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • C++ const与constexpr区别小结

    C++ const与constexpr区别小结

    C++11标准中,const用于为修饰的变量添加只读属性,而constexpr关键字则用于指明其后是一个常量,本文主要介绍了C++ const与constexpr区别小结,感兴趣的可以了解一下
    2024-03-03
  • C语言从基础到进阶全面讲解数组

    C语言从基础到进阶全面讲解数组

    数组是一组有序的数据的集合,数组中元素类型相同,由数组名和下标唯一地确定,数组中数据不仅数据类型相同,而且在计算机内存里连续存放,地址编号最低的存储单元存放数组的起始元素,地址编号最高的存储单元存放数组的最后一个元素
    2022-05-05
  • C语言实现计算树的深度的方法

    C语言实现计算树的深度的方法

    这篇文章主要介绍了C语言实现计算树的深度的方法,针对数据结构中树进行操作的方法,在算法设计中比较常见,需要的朋友可以参考下
    2014-09-09
  • C++实现简单单向链表

    C++实现简单单向链表

    这篇文章主要为大家详细介绍了C++实现简单单向链表,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • C语言实现页面置换算法(FIFO、LRU)

    C语言实现页面置换算法(FIFO、LRU)

    这篇文章主要介绍了通过C语言实现的两种页面置换算法:先进先出(FIFO)页面置换算法和最近最久未使用(LRU)页面置换算法。文中的代码具有一定的学习或工作价值,快来跟随小编学习一下吧
    2021-12-12
  • c++ 排查内存泄漏的妙招

    c++ 排查内存泄漏的妙招

    这篇文章主要介绍了c++ 如何用辅助类排查内存泄漏,帮助大家更好的理解和学习使用c++,感兴趣的朋友可以了解下
    2021-03-03
  • C语言实现简易连连看游戏

    C语言实现简易连连看游戏

    这篇文章主要为大家详细介绍了C语言实现简易连连看游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • c++实现单纯形法现行规划问题的求解(推荐)

    c++实现单纯形法现行规划问题的求解(推荐)

    这篇文章主要介绍了c++实现单纯形法现行规划问题的求解,本文针对问题通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-04-04
  • c++ map索引不存在的key可能导致的后果分析

    c++ map索引不存在的key可能导致的后果分析

    这篇文章主要介绍了c++ map索引不存在的key可能导致的后果分析,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12

最新评论