美文网首页C/C++知识点
C++小知识:不要去做编译器的工作

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

作者: Python编程导师 | 来源:发表于2019-01-10 21:22 被阅读2次

对于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 源代码之前,所有其他的测试都没能发现这个错误。这里推荐一下小编的c/c++编程交流群:941636044,有兴趣与小编一起交流的小伙伴可以一起交流哦!

正确的代码:

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语言c++编程交流群,有兴趣与小编一起交流的小伙伴可以一起交流哦!

相关文章

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

    对于C++编程的老鸟来说,有时候他们喜欢把一些东西按照编译器的工作原理进行改写,以便提高代码的运行效率。这么做确实...

  • C++编译过程

    C++ 编译过程在介绍编译器之前,先简单地说一下 C++ 的编译过程,以便理解编译器的工作。编译(compilin...

  • 2019年需要学习的专业知识

    接下来的学习计划 软件知识体系结构 基础知识 C/C++编程语言 数据结构 算法分析与实现 中级知识 编译器原理 ...

  • 单链表

    要找工作了,最近开始刷题啦,写一些关于C++的小知识。 1.链表结构体不要忘了}的分号“;”,这个很容易错 str...

  • C++——this指针

    this指针的出现是因为在早期没有c++编译器,c++程序只能使用c语言的编译器进行编译。所以c++的程序先需要翻...

  • 如何识别C++编译以后的函数名

    如何识别C++编译以后的函数名(demangle) C/C++语言在编译以后,函数的名字会被编译器修改,改成编译器...

  • CMake 的基本使用

    准备工作 最新版的 CMake(3.8)。 C/C++ 编译器(GCC,MSVC,clang)。 编辑器(CLio...

  • Thrift安装0.9.1

    1.依赖安装 Thrift的编译器使用C++编写的,在安装编译器之前,首先应该保证操作系统基本环境支持C++的编译...

  • 《深度探索c++对象模型》(一)

    前述 看完《深度探索c++对象模型》,心中对c++编译器在编译期间所做的处理有了更深入的认识,我想,除了对编译器本...

  • Boolan微专业-面向对象高级编程学习笔记(Week01)

    C++简介 书籍推荐 语言:C++Primer(C++第一个编译器者著), The C++ Programming...

网友评论

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

    本文链接:https://www.haomeiwen.com/subject/icmorqtx.html