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

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

void main(){

char *x="abc";
char *y="defgh";
   printlen(x,y);

}

strlen(s) is 3 and strlen(t) is 5, so why is strlen(s)-strlen(t)>c evaluating to true?

dbush
  • 205,898
  • 23
  • 218
  • 273
rakesh patel
  • 61
  • 1
  • 8
  • Read the parentheses as `if`. Read the question mark as `then`. Read the colon as `else`. So `((strlen(s)-strlen(t)>c)?strlen(s):strlen(t))` evaluates to "if (strlen(s)-strlen(t)>0) then strlen(s) else strlen(t)" – torstenvl Oct 29 '21 at 02:13
  • https://stackoverflow.com/q/52082709/1216776 – stark Oct 29 '21 at 02:19
  • You would do better to reorganize the condition to `(strlen(s) > strlen(t))`, or if `c` might not be zero, then `(strlen(s) > strlen(t) + c)`. Avoid subtracting unsigned quantities. – Jonathan Leffler Oct 29 '21 at 02:20
  • See also [What should `main()` return in C and C++?](https://stackoverflow.com/q/204476/15168) – Jonathan Leffler Oct 29 '21 at 02:21

2 Answers2

4

The strlen function returns a value of type size_t which is unsigned.

So subtracting unsigned 3 from unsigned 5 results in a very large unsigned number. This number is greater than 0 so the condition is true, causing strlen(s) to be evaluated and assigned to len.

The result of the subtraction should be cast to int to properly store a signed value.

int len=(((int)(strlen(s)-strlen(t))>c)?strlen(s):strlen(t));

Better yet, cast the result of each strlen to avoid an out-of-range conversion from unsigned to signed which is implementation defined:

int len= ((int)strlen(s)-(int)strlen(t))>c)?strlen(s):strlen(t);
dbush
  • 205,898
  • 23
  • 218
  • 273
  • Or `ssize_t`, depending on what range of lengths are expected (in practice, `int` is probably fine). – Tom Karzes Oct 29 '21 at 02:17
  • 1
    @rakeshpatel Glad I could help. Feel free to [accept this answer](https://stackoverflow.com/help/accepted-answer) if you found it useful. – dbush Oct 29 '21 at 04:15
  • Conversion of a value out of the `int` range to `int` is implementation-defined. `(int) strlen(s) - (int) strlen(t)` would be preferred over `(int) (strlen(s) - strlen(t))` because the former would have implementation-defined behavior only in the rare cases where one string length exceeds the `int` range, whereas the latter has implementation-defined behavior in the common case that `s` is shorter than `t` (as well as when the difference between string lengths exceeds the `int` range). – Eric Postpischil Oct 29 '21 at 10:41
  • Likely better would be `strlen(s) > strlen(t) + c`, which has problems only when `strlen(t)` + `c` exceeds the range of `size_t`. – Eric Postpischil Oct 29 '21 at 10:43
0
int len=((strlen(s)-(int)strlen(t)>c)?strlen(s):strlen(t));
printf("%d",len);

is equal:

int len;

if((strlen(s) - strlen(t) > c)
    len = strlen(s);
else
    len = strlen(t);
printf("%d",len);

Firstly, printf("%d",len); is unconditional. Whatever len(s) - strlen(t) > c is true or false, printf("%d",len); get executed.

Second, strlen return size_t, which is an alias for unsigned long long, so (strlen(s) - strlen(t) > c) is always true.

You should typecast it to an int

int len=(((int)strlen(s)-(int)strlen(t)>c)?strlen(s):strlen(t));

  • `size_t` is generally not an `unsigned int`. It usually has a larger type, typically `unsigned long long`. – Tom Karzes Oct 29 '21 at 08:48
  • `(int)strlen(s)-strlen(t)` is useless. Because `size_t` is unsigned and almost always at leas as wide as `int`, the `-` operator will convert `(int)strlen(s)` to `size_t`, and the result will be unsigned. – Eric Postpischil Oct 29 '21 at 10:37