【问题标题】:why is -1>strlen(t) true in C? [duplicate]为什么 -1>strlen(t) 在 C 中为真? [复制]
【发布时间】:2015-07-29 12:05:19
【问题描述】:

在 VS2013 中处理这段小代码,但由于某种原因它没有打印。似乎 -1>strlen(str)

有人知道我做错了什么

char *str="abcd";
if(-1<strlen(str))
printf("The size of the string is %d", strlen(str));    
return 0;

【问题讨论】:

  • strlen(str)的输出值是多少?
  • 可能是它返回无符号值并且会破坏事情
  • 最好在编译器上打开最大设置警告
  • 这是因为类型提升和所谓的环绕。 -1 被提升为size_t 并变为SIZE_MAX
  • 这样做的原因why(整数提升和通常的算术转换)无关紧要。这显然是一个程序员问题,因为您永远不应该期望 -1 大于或等于 any 字符串的长度。如果你做傻事,你必须考虑到你可能看起来(据说)奇怪的结果。

标签: c strlen


【解决方案1】:

有人知道我做错了什么

strlen() 返回一个size_t,它是一个无符号整数类型。 -1 解释为无符号整数是一个很大的值,因此它最终会大于字符串的长度。当您尝试比较有符号和无符号值时,您可以使用 gcc 中的 -Wsign-compare 标志和其他一些编译器来警告您。

此外,将字符串的长度与-1 进行比较也没有多大意义。长度永远不能是负数;它总是将是0 或更大。因此,您可能需要重写代码以针对 0 进行测试,或者以其他方式正确实现您尝试测试的任何条件。

if(-1<strlen(str)) printf("The size of the string is %d", strlen(str));

在这段代码中,您可能有理由期望测试总是成功并且printf() 会执行,因为长度总是0 或更大。但是您会发现测试实际上失败了,并且printf() 从未发生过,因为-1 被提升为无符号,以便可以将其与size_t 进行比较。简单的解决方案是完全删除条件:您知道测试将始终成功,因此不需要它。只需删除 if*:

printf("The size of the string is %zu", strlen(str));

*另外,将打印格式说明符从 %d 更改为 %zu,因为正如 Matt McNabb 在评论中指出的那样,您正在尝试打印 size_t

【讨论】:

  • 你可以告诉 OP 编译器警告,如果启用,可以防止这种错误。
  • @chqrlie 好建议;完成。
【解决方案2】:

strlen(str) 返回一个无符号整数。将有符号整数与无符号整数进行比较时,编译器会将有符号值转换为无符号值。当转换为无符号时,-1 变为 2^32 - 1(假设 strlen 返回一个 32 位整数),它大于您要比较的字符串的长度。

【讨论】:

  • 不要假设 size_t 是 32 位长。
  • 你可以告诉 OP 编译器警告,如果启用,可以防止这种错误。
  • 转换为size_t,而不是intstrlen 返回 size_t,如今超过 32 位的情况很常见。
【解决方案3】:

strlen 返回一个size_t 类型的值。这是一个无符号整数类型。

在 C 语言中,将有符号值与相应无符号类型的值进行比较的规则是将有符号值转换为无符号值。

如果值是不同大小的类型,例如如果您的系统有 4 字节 int 和 8 字节 size_t,则规则是将较小类型的值转换为较大类型的值输入。

无论哪种方式,这意味着-1 被转换为size_t,导致SIZE_MAX 这是一个很大的正值。 (无符号类型不能包含负值)。

这个大的正值大于字符串的长度,所以小于比较返回 false。

【讨论】:

  • 你可以告诉 OP 编译器警告,如果启用,可以防止这种错误。
  • @chqrlie 取决于编译器和设置的质量。我倾向于禁用有符号-无符号警告,因为它们往往是误报。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-12
  • 2021-05-25
相关资源
最近更新 更多