【问题标题】:Why does strlen in a if statement behave oddly? [duplicate]为什么 if 语句中的 strlen 行为异常? [复制]
【发布时间】:2020-06-12 12:55:24
【问题描述】:
#include <stdio.h>
#include <string.h>

int main()
{
    const char str[11]= "Hello World";
    if(-1 > strlen(str)){
        printf(str);
    }

    return 0;
}

这个 if 条件应该总是返回 false。但这里不是。 但是,如果我将 strlen(str) 值放入另一个变量并与之进行比较,那么它会按预期工作。 我在这里缺少什么? 它是编译器依赖还是什么?

【问题讨论】:

  • 您的str 没有以空值结尾,因为您没有为空值留出足够的空间。所以在它上面调用strlen 会跑到最后,这会导致未定义的行为。在其上调用 printf 也是未定义的。
  • 另外,请记住 strlen 返回一个 unsigned 值 (size_t)。
  • 开启编译器警告-Wall -Wextra
  • 显然C 的新手很容易激怒更有经验的C 程序员,只需不查看编译器警告,并在发布的示例代码中调用 UB。还是所有的向下点击只是盲目的堆积?说真的,现在已经收到消息了。在这里,对向下点击触发手指进行更多的自我控制可能是个好主意。
  • @ryyker:确实。这个问题很清楚,可以回答。那里也有可编译的代码,实际和预期的行为都有很好的记录。

标签: c++ c implicit-conversion unsigned strlen


【解决方案1】:

strlen 返回一个unsigned 类型。

这具有将-1 转换为unsigned 类型的效果,这是一个很大的数字。

该数字将大于strlen 结果,因此程序控制到达if 语句体。

如果您将strlen 的值分配给signed 类型的变量,并使用它进行比较,则-1 的转换将不会发生,if 语句的行为将与您预期的一样。


请注意,从技术上讲,您的代码行为是未定义的,该字符串需要 12 个元素(对于 NUL 终止符),而不是 11 个,strlen 需要 NUL 终止符才能正常工作。最好让编译器来做计数,写

const char str[] = "Hello World";

【讨论】:

  • 如果您引用 C 标准中 二进制算术转换 的相应规则将很有帮助,以帮助 OP 自行回答此类问题。跨度>
  • @RolandIllig:多标签阻止了我这样做。我还不得不对在 OP 出于类似原因提出的示例中明确排除 NUL 含糊其辞:C 和 C++ 的规则在这方面有所不同。
  • 它可能会阻止你,但不会阻止我。对于 C11,它在标准的第 6.3.1.8 节中。
  • @RolandIllig 是对的。仅仅因为 OP 滥用标签,并不意味着您不能引用。顺便说一句,提供的代码是 C 代码。
  • 在大约 2 小时内获得 14 次投票。那应该有人顶。 ;-)
猜你喜欢
  • 1970-01-01
  • 2012-08-09
  • 2015-05-06
  • 1970-01-01
  • 2021-01-28
  • 2014-04-23
  • 2021-12-23
  • 1970-01-01
  • 2016-12-08
相关资源
最近更新 更多