2

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;
}
Costantino Grana
  • 3,132
  • 1
  • 15
  • 35
Placido
  • 23
  • 2
  • 1
    What type of value does [`strlen()`](https://port70.net/~nsz/c/c11/n1570.html#7.24.6.3) return? – Andrew Henle Dec 16 '20 at 12:10
  • 6
    The problem is you're using `-3` in an unsigned comparison. Since `strlen` returns a `size_t`, which is an unsigned integer type, comparing the result with an `int` results in the `int` being converted to a `size_t` as well. – Tom Karzes Dec 16 '20 at 12:11
  • 2
    Your compiler should be giving you a warning. If not, you definitely should rise the warning level. – Costantino Grana Dec 16 '20 at 12:15
  • [Why sizeof(int) is not greater than -1?](https://stackoverflow.com/q/24466857/995714) – phuclv Dec 16 '20 at 13:20

3 Answers3

4

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.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

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.

Krishna Kanth Yenumula
  • 2,533
  • 2
  • 14
  • 26
0

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.

Sagun Devkota
  • 495
  • 3
  • 10
  • But `-3` downcast to unsigned should still be smaller than strlen of hello, or am I misunderstanding what downcast does? – Ivan C Dec 16 '20 at 12:22
  • Try.`int I=-3;printf("%u",(unsigned int)I);`Then run your code you will get value something like 4294967293 which is bigger than 5. – Sagun Devkota Dec 16 '20 at 12:45