-2

In the below code length of string s in 3 and length of t is 5. So, 3-5 = -2 which is smaller than 0. Then, why does the below code print 3?

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

void printlength(char *s, char *t){
    unsigned int i=0;
    int len = ((strlen(s) - strlen(t))> i ? strlen(s):strlen(t));
    printf("%d",len);
}

int main()
{
    char *x ="abc";
    char *y ="defgh";
    printlength(x,y);
    return 0;
}
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85

4 Answers4

0

So, 3-5 = -2

Thats for signed ints, for size_t which strlen() returns and is unsigned, that's a pretty big number.

Yunnosch
  • 26,130
  • 9
  • 42
  • 54
Slava
  • 43,454
  • 1
  • 47
  • 90
0

when -2 is converted to an unsigned int the result is the unsigned int value (UINT_MAX + 1- 2 or UINT_MAX - 1) , which is greater than i. strlen returns size_t which is an unsigned data type.

Also size_t is the correct type for len which we would print with printf("%zu",len).

Suprisingly when you compared the result of subtraction with i and the value of i is 0. You can do this

size_t slen = strlen(s);
size_t tlen = strlen(t);
printf("%zu\n", (slen > tlen)? slen : tlen);
user2736738
  • 30,591
  • 5
  • 42
  • 56
0

Your problem is with subtracting greater unsigned value from the smaller one.

 `(unsigned) 3 - (unsigned) 5` =  (unsigned) 4294967294 which is > 0.

Use proper types for your calculations and proper logic. Remember that strlen returns value of type size_t. No need to repeat strlen operation for the same string.

The improved version of your program could look like this:

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

void printlength(char *s, char *t){

    size_t len; 

    size_t sLen = strlen(s);
    size_t tLen = strlen(t);        

    if(sLen > tLen)
        len = sLen - tLen;
    else
        len = tLen - sLen;       

    printf("len = %u\n\n",len);

    printf("NOTE: (unsigned) 3 - (unsigned) 5 =  %u", -2);
}

int main()
{
    char *x ="abc";
    char *y ="defgh";

    printlength(x,y);

    return 0;
}

OUTPUT:

len = 2

NOTE: (unsigned) 3 - (unsigned) 5 =  4294967294
sg7
  • 6,108
  • 2
  • 32
  • 40
0

The prototype of strlen() is:

size_t strlen ( const char * );

It's return value type is size_t, which in most cases, is an unsigned integer type (usually unsigned int or unsigned long.

When you do subtraction between two unsigned integers, it will underflow and wrap around if the result is lower than 0, the smallest unsigned integer. Therefore on a typical 32-bit system, 3U - 5U == 4294967294U and on a typical 64-bit system, 3UL - 5UL == 18446744073709551614UL. Your test of (strlen(s) - strlen(t)) > i has exactly the same behavior of strlen(s) == strlen(t) when i == 0, as their length being identical is the only case that could render the test being false.

It's advised to avoid using subtraction when comparing intergers. If you really want to to that, addition is better:

strlen(s) > strlen(t) + i

This way it's less likely to have unsigned integer overflow.

By the way, if you save the length of the strings in variables, you can reduce an extra call to strlen(). And since you do not modify the strings in your function, it is better to declare the function parameters as const char*. It's also recommended that you do

const char *x ="abc";
const char *y ="defgh";

since string literals cannot be modified. Any attempt to modify a string literal invokes undefined behavior.

iBug
  • 35,554
  • 7
  • 89
  • 134