【问题标题】:Why (positive_integer < negative_integer) is getting evaluated to be true?为什么 (positive_integer <negative_integer) 被评估为真?
【发布时间】:2023-03-20 11:01:01
【问题描述】:
$ gcc --version  
gcc (Debian 4.9.2-10) 4.9.2

在下面的代码 sn-p 中,为什么表达式 100 &lt; strlen(str) - 4 被评估为真?

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[50];

    scanf("%s", str);
    printf("%d\n", strlen(str) - 4);

    if(100 < (strlen(str) - 4))
        printf("NOT POSSIBLE!\n");

    return 0;
}

终端:

$ gcc so.c -o so  
$ ./so  
foo
-1
NOT POSSIBLE!  

通过实验我发现:

  1. if 表达式对于任何 positive_int、negative_int 对的计算结果为 true,这样 positive_int &lt; negative_num(这是荒谬的),其中negative_int 是 strlen 函数调用的形式(参见 2。)
  2. 如果我们将strlen 替换为硬编码的负整数,则if 的计算结果与预期一样为falsestrlen 似乎有问题。

【问题讨论】:

  • 因为 size_t 是无符号的。您可能会写if (100 + 4 &lt; strlen(str)) 以避免出现负数问题,从而获得正确的结果。
  • 有关size_t的更多信息,请参见this So post

标签: c if-statement strlen


【解决方案1】:

由于strlensize_t类型,所以4被转换为(无符号)size_t,然后从strlen的返回值中扣除,再与100比较结果。

6.3.1.8 常用算术转换
....
否则,如果两个操作数都具有有符号整数类型或都具有无符号 整数类型,具有较小整数转换等级类型的操作数是 转换为具有更高等级的操作数的类型。

否则,如果具有无符号整数类型的操作数的秩大于或 等于另一个操作数的类型的等级,然后操作数与 有符号整数类型转换为无符号操作数的类型 整数类型。

7.24.6.3 strlen 函数
....
size_t strlen(const char *s);

7.19 常用定义
....
size_tsizeof运算符结果的无符号整数类型;


附:顺便说一句,即使在更简单的情况下,作为

if (strlen("") < -1)
    printf("OK\n");
else
    printf("NOK\n");

,输出将是OK

【讨论】:

  • @SouravGhosh 也许这取决于标准的版本。我有N1570
  • 所以这里3strlen 返回的无符号整数,所以4 也将转换为无符号整数。结果如何,即(unsigned)3 - (unsigned)4?标准是否保证两个无符号数的运算只会产生无符号值?
  • @owacoder 好的。我想我明白了。 (unsigned)3 - (unsigned)4 的结果等于 (unsigned)(-1),它比 (unsigned) 100 大得多。是正确的解释吗?
  • @rootkea 我更新了帖子以包含“如果两个操作数都具有有符号整数类型或都具有无符号整数类型...”。
【解决方案2】:

strlen() 将返回一个无符号值,因此strlen(str) - 4 将是“非常大”的无符号数,它会大于100

如果您不会处理很长的字符串,请尝试将返回值转换为 int

#include <stdio.h>
#include <string.h>

int main(void)
{
    char str[50];

    scanf("%49s", str); /* specify size to avoid buffer overrun */
    printf("%d\n", (int)strlen(str) - 4);

    if(100 < ((int)strlen(str) - 4))
        printf("NOT POSSIBLE!\n");

    return 0;
}

【讨论】:

  • if (100u &lt; (strlen(str) - 4)) 会更好。
  • 100u + 4u &lt; strlen(str) 更适合避免不必要的包装。
  • 对不起。我只是意识到它不会有同样的效果。
【解决方案3】:

strlen 返回一个size_t 类型的无符号整数。当从无符号 3 中减去 4 时,无符号整数将回绕到可表示的最大数字,因此总是大于 100。

【讨论】:

    【解决方案4】:

    引用C11,第 7.23.6.3 章,strlen() 函数

    size_t strlen(const char *s);

    strlen() 的返回类型是 size_t,并且根据第 §7.19 章,(强调我的

    size_t

    这是sizeof运算符结果的无符号整数类型;

    1004int 字面量,这里是signed 类型,参考章节§6.4.4.1

    整数常量的类型是其值可以在对应列表中的第一个 被代表。

    您正在尝试执行涉及 signed 类型和 unsigned 类型的算术运算(减法),因此在比较之前,有符号类型将提升为 unsigned 类型。因此,结果为无符号类型,比较的最终结果为 TRUE。

    【讨论】:

      猜你喜欢
      • 2020-04-03
      • 2014-05-19
      • 2014-02-16
      • 2018-07-01
      • 2017-04-28
      • 1970-01-01
      • 2021-11-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多