为什么 (positive_integer < negative_integer) 被评估为 true?

Why (positive_integer < negative_integer) is getting evaluated to be true?

$ gcc --version  
gcc (Debian 4.9.2-10) 4.9.2

在下面的代码片段中,为什么表达式 100 < 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 对的计算结果为真,使得 positive_int < negative_num(这是荒谬的)其中 negative_int 在strlen 函数调用的形式(参见 2.)
  2. 如果我们将 strlen 替换为硬编码的负整数,则 if 将按预期计算为 falsestrlen.
  3. 好像有问题

由于strlen的类型为size_t4被转换为(无符号)size_t,然后从strlen的[=30=中扣除] 值,然后将结果与 100.

进行比较

6.3.1.8 Usual arithmetic conversions
....
Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank.

Otherwise, if the operand that has unsigned integer type has rank greater or equal to the rank of the type of the other operand, then the operand with signed integer type is converted to the type of the operand with unsigned integer type.

7.24.6.3 The strlen function
....
size_t strlen(const char *s);

7.19 Common definitions
....
size_t which is the unsigned integer type of the result of the sizeof operator;


P.S。顺便说一句,即使在更简单的情况下,如

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

,输出将是 OK.

strlen() 将 return 为无符号数,因此 strlen(str) - 4 将是无符号数,即 "very big",并且大于 100

如果您不想处理很长的字符串,请尝试将 return 值转换为 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;
}

strlen returns size_t 类型的无符号整数。从无符号 3 中减去 4 时,无符号整数将回绕到最大可表示数,因此始终大于 100。

引用 C11,章节 §7.23.6.3,strlen() 函数

size_t strlen(const char *s);

strlen() 的 return 类型是 size_t,根据第 7.19 章,(强调我的

size_t

which is the unsigned integer type of the result of the sizeof operator;

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

The type of an integer constant is the first of the corresponding list in which its value can be represented.

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