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

时间:2015-12-27 13:40:46

标签: c if-statement strlen

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

在以下代码片段中,为什么表达式100 < strlen(str) - 4被评估为true?

#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. 对于任何positive_int,negative_int对,if表达式的计算结果为true,使得positive_int < negative_num(这是荒谬的)其中negative_int是strlen函数调用的形式(参见2.)
  2. 如果我们将strlen替换为硬编码的负整数,则if会按预期评估为false。看起来strlen出现了问题。

4 个答案:

答案 0 :(得分:4)

由于strlen的类型为size_t4会转换为(无符号)size_t,然后从strlen的返回值中扣除,然后结果与100进行比较。

  

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

     

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

     

7.24.6.3 strlen功能
....
  size_t strlen(const char *s);

     

7.19通用定义
....
  size_t   这是sizeof运算符的结果的无符号整数类型;

P.S。顺便提一下,即使在更简单的情况下,也是如此

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

,输出为OK

答案 1 :(得分:4)

listview.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, final View view, int position, long id) { //your code } }); 将返回无符号值,因此strlen()将是无符号数,“非常大”,并且会大于strlen(str) - 4

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

int

答案 2 :(得分:2)

#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的无符号整数。当从无符号3中减去4时,无符号整数将包装到最大的可表示数字,因此总是大于100。

答案 3 :(得分:2)

引用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类型。因此,结果是unsigned类型,比较的最终结果为TRUE。