【问题标题】:Purpose behind comparing string pointer to NULL as well as NULL character将字符串指针与 NULL 以及 NULL 字符进行比较的目的
【发布时间】:2017-11-10 19:18:25
【问题描述】:

在尝试从source 编译xtrabackup 时,我在sql/sql_acl.cc 中发现了一段特殊的代码行,GCC 拒绝在没有更宽松设置的情况下进行编译。这行是问题所在:

if (combo->plugin.str == NULL || combo->plugin.str == '\0')

立即引发以下错误:

错误:ISO C++ 禁止指针和整数之间的比较

考虑到有问题的代码,这似乎完全合理。 plugin 值属于这种类型:

struct st_mysql_lex_string
{
  char *str;
  size_t length;
};

这是一个简单的 MySQL 内部结构,表示字符串指针 + 长度对,所以在这种情况下,str 只是char*,没什么特别的。

我知道跨平台开发和处理巴洛克式编译器环境可能需要一定程度的偏执狂,但是如果有的话,这种双重 NULL 检查的理由是什么?我想不出如果第一个子句不是,第二个子句怎么会是真的,但我可能会遗漏一些不寻常的边缘情况。

【问题讨论】:

  • C++ nullptr 也许?
  • 看起来像一个错误。 if 声明对我来说没有多大意义。
  • GCC->g++ 也许?
  • 大概是这样设计的吧? if (combo->plugin.str == NULL || *combo->plugin.str == '\0') 仅在不为空时取消引用?
  • 看起来他们可能在其他地方也有同样的错误,比较指向'\0'的指针。它说明了为什么我们可以从一开始就使用nullptr

标签: c++ gcc cross-platform


【解决方案1】:

我的假设是,目的是支持空终止是可选的字符串(因此有一个长度字段)。在这种情况下,包含 '\0' 的无效字符串将具有 valid 大小 1。这就是为什么此健全条件不使用长度的原因。无论如何,有一个错误使第二个条件始终为“真”,因此毫无意义,代码可能看起来像:

if (combo->plugin.str == NULL || combo->plugin.str [0] == '\0')

【讨论】:

  • 大概就是这个意思。奇怪的是,这种模式通过该代码重复出现。通常你会定义一个宏或一个内联函数来帮助正确地断言它。编译器拒绝这个很好,因为它似乎确实是一个错误。这一切都基于 MySQL 内部,因此很难说出这种反模式的确切来源。
  • 现在这个bug已经修复(实际上是8天前)。好吧,这可能不是您见过的最惯用的代码。实际上,在代码中的其他地方对这种情况进行了正确的处理:const char *new_plugin= (combo->plugin.str && combo->plugin.str[0]) 我检查了历史记录,似乎这条特定的行是从其他地方复制粘贴的。这就是为什么这种“模式”会重复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-03
  • 2013-01-17
  • 1970-01-01
  • 2014-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多