为什么有时会对一个字符串进行两次检查?

Why do you sometimes do two checks on a string?

我看到了这段代码:

char *str;
// Some code
if (! str || ! *str)
    return str;

为什么要检查! *strif (! str)还不够吗?

这取决于您要检查的内容:

  • !str 检查 str 是否为 NULL。
  • !*str 检查 str 中的第一个字符是否为 NUL 字节 ('\0')

合并后,如果 s 为 NULL,或者 s 指向 NUL 字符,它们将 return 's'

来看一个道理table:

str    *str    !str   !*str   !str || !*str
T      T       F      F       F
F      T       T      F       T
T      F       F      T       T
F      F       T      T       T

所以如果 str 是一个 NULL 指针,那么 !str 将为真,并且总是返回 str。如果 str 不是 NULL 指针,则仅当 *str 是 NUL 终止符时才会返回 str

请注意,您可以使用布尔代数将其重写为!(str && *str)。括号用英文可以表示为"non-empty string"。所以整个条件是 "not non-empty string".

请注意,它之所以起作用是因为 短路 这意味着如果 ||&& 的结果只能由左操作数确定,则不会计算右操作数。否则,当 str 是 NULL 指针时,取消引用将产生未定义的行为。

在这里,有一个非常重要的逻辑问题需要注意。仅仅因为一个字符串不是 "not empty" 并不一定意味着它是空的。但这在一定程度上取决于解释。共有三种情况,这里是所有情况的示例。

  • "Hello, World[=21=]" - 绝对不为空
  • "[=22=]" - 肯定是空的
  • NULL - 绝对不是"not empty",但它是空的吗?

我可能会补充说,这是返回 str 的一个非常奇怪的条件。这不是你通常会做的事情。