将字符串指针与NULL以及空字符进行比较的目的

3

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

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

立即引发以下错误:

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

鉴于所涉及的代码,这似乎是完全合理的。 plugin 值属于此类型:

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

这是一个简单的MySQL内部结构,表示一个字符串指针 + 长度对。因此,在这种情况下,str 只是一个普通的 char* 指针。

我知道跨平台开发和处理复杂的编译器环境可能需要一定程度的谨慎,但是有什么理由来证明这个双重NULL检查的必要性呢?如果第一个子句不成立,我想不出第二个子句会如何成立,但我可能会忽略一些不寻常的边缘情况。


1
C++ nullptr 可能吗? - Ed Heal
GCC -> g++ 可能吗? - Ed Heal
5
也许是这样打算的吗?if (combo->plugin.str == NULL || *combo->plugin.str == '\0') 只有在不为 null 时才进行解引用操作? - Galik
@Galik 感谢您的确认。如果您想将其作为答案添加,我认为这是我们能做到的最好的。 - tadman
1
看起来他们可能在其他地方也有相同的错误,比较指针和 '\0'。这说明为什么我们一开始就应该有一个 nullptr - Galik
显示剩余4条评论
1个回答

3

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

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

这可能是意图。奇怪的是,这种模式在代码中重复出现。通常,您会定义一个宏或内联函数来帮助正确地进行断言。很好,编译器拒绝了这个错误,因为它似乎确实是一个错误。这一切都基于MySQL内部,所以很难确定这种反模式的确切起源。 - tadman
1
现在这个 bug 已经修复了(实际上是 8 天前)。嗯,这可能不是你见过的最惯用的代码。 实际上,在代码的其他地方有一个正确的处理方式: const char *new_plugin= (combo->plugin.str && combo->plugin.str[0]) 我已经检查了历史记录,似乎这一行特定的代码是从其他地方复制粘贴过来的。这就是为什么这个“模式”会重复出现的原因。 - Lesh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接