if statement selects the wrong condition

Viewed 122

I have a problem with this code: I don't know why it prints B and not A, since the condition is true. strlen(x) is clearly greater than i. Can you help me?

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

int main()
{
   char x[]="Hello";
   int i = -3;
   
   if(strlen(x)>i)
   {
       printf("A");
   }
   else
   {
       printf("B");
   }
    return 0;
}
3 Answers

The standard function strlen is declared like

size_t strlen(const char *s);

where the type size_t is an implementation defined unsigned integer type the rank of which is not less than the rank of the type int. Usually the type size_t is defined as an alias for the type unsigned long.

In the expression used as a condition of the if statement

if(strlen(x)>i)

the compiler determines the common type of operands using the usual arithmetic conversions. That is the operand i is converted to the type size_t by propagating the sign bit. And as a result the value of the converted operand is a very big unsigned integer of the type size_t that is greater than the returned value of the call of strlen. So the condition evaluates to the logical false.

Here is a demonstrative program.

#include <stdio.h>

int main(void) 
{
    int i = -3;
    
    printf( "( size_t )i = %zu\n", ( size_t )i );
    
    return 0;
}

Its output might look like

( size_t )i = 18446744073709551613

If you want to get the expected by you result in your program you should write

if( ( int )strlen(x)>i)

or for example

if( ( long int )strlen(x)>i)

That is you need to cast the value returned by the function strlen to some signed integer type.

From C17 document, 6.3.1.8, page number 39

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

size_t strlen(const char *s);

Here, strlen(x) return value of type size_t (unsigned long int). But i is of type int. The rank of size_t is greather than the rank int. So, i will be promoted to size_t.

Unsigend value of -3 is 4294967293 (in my system). And strlen(x) = 5 , so it will print the else statement.

You are trying to compare signed int with unsigned int. Try if(signed(strlen(x))>i){} Or else you may change the value of I to positive int.

Related