Search code examples
cif-statementstrlen

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


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

In the following code snippet why is the expression 100 < strlen(str) - 4 getting evaluated as 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;
}

Terminal:

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

From experimenting a bit I found out :

  1. the if expression evaluates to true for any positive_int, negative_int pair such that positive_int < negative_num (which is absurd) where negative_int is in the form of strlen function call (see 2.)
  2. if we replace the strlen with a hard coded negative integer then if evaluates to false as expected. Looks like there's something wrong with strlen.

Solution

  • Since strlen has type size_t, 4 is converted to (unsigned) size_t, then deducted from strlen's return value, and then the result is compared with 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. BTW, even in a simpler case, as

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

    , the output would be OK.