2
int main()
{
    unsigned int c = -1;
    char *s = "Abc";
    char *x = "defhe";
    ((strlen(s)-strlen(x))>c)? printf(s): printf(x);
}

the value of c is 4294967295 and the value of (strlen(s)-strlen(x)) is 4294967294 it should print the x but it is printing the s value.I am not getting why it is like that

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Chandra Sekar
  • 302
  • 1
  • 13

3 Answers3

6

the value of c is 4294967295 and the value of (strlen(s)-strlen(x)) is 4294967294

It isn't necessarily true that (strlen(s)-strlen(x)) yields 4294967294. It depends on the value of SIZE_MAX on your system.

If SIZE_MAX is 18446744073709551615 (typically on a 64-bit system) then (strlen(s)-strlen(x)) will be 18446744073709551614 which is obviously greater than 4294967295 (assuming UINT_MAX is 4294967295). Hence, you see printf(s); getting printed.

Use a printf() statement to see the values and understand:

printf("%zu %u\n", strlen(s)-strlen(x), c);
P.P
  • 117,907
  • 20
  • 175
  • 238
  • From the ANSI standard (I don't have C99, but it's the same behavior):A.6.2 Undefined behavior * An arithmetic operation is invalid (such as division or modulus by 0) or produces a result that cannot be represented in the space provided (such as overflow or underflow) ($3.3). strlen() returns size_t which is unsigned. You're underflowing and in the realms of undefined behavior. I've seen this be inconsistent in statements compiled by the same compiler, let alone one compiler to the next. – BigBobby Feb 14 '17 at 15:06
  • 2
    @BigBobby "A computation involving unsigned operands can never overflow,..." C11dr §6.2.5 9 This is no UB with the comparison. – chux - Reinstate Monica Feb 14 '17 at 15:12
  • 3
    @BigBobby There's no undefined behaviour in the code. All the conversions (and promotions) happen as defined by the C standard. Please explain which "operation is invalid". By the way, unsigned types do *not* overflow (or underflow). They just wrap around using reduction modulo. – P.P Feb 14 '17 at 15:12
  • @chux - I said underflow, not overflow. – BigBobby Feb 14 '17 at 15:12
  • 2
    @BigBobby There's no "underflow" either. – P.P Feb 14 '17 at 15:14
  • @usr - Two unsigneds are being subtracted and being compared to an unsigned. What promotion do you think is happening? – BigBobby Feb 14 '17 at 15:14
  • 2
    @BigBobby True that our comment said "underflow", yet that makes no difference. Still no UB. – chux - Reinstate Monica Feb 14 '17 at 15:14
  • @BigBobby Unsigned integers, by definition, can't overflow or underflow. Their "wrap around" behaviour is well-defined by the C standard and it's not undefined behaviour. Please do not downvote if you don't know that. – P.P Feb 14 '17 at 15:17
  • @usr - Are you trying to strictly define underflow as when a number gets too small to be represented by a float, as opposed to getting a negative result when two unsigned integers are subtracted? The standard refers to both as underflow...the OP is subtracting two unsigned numbers and underflowing, and assigning a negative number to a unsigned integer in the first place. – BigBobby Feb 14 '17 at 15:17
  • 1
    @BigBobby The conversion of `-1` to `unsigned` is well defined per "if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type" Unclear if you see this as an issue. – chux - Reinstate Monica Feb 14 '17 at 15:20
  • @BigBobby-- where in the Standard is underflow resulting from subtraction of `unsigned` types mentioned? – ad absurdum Feb 14 '17 at 15:24
  • @usr To be fair, the spec is not obvious about unsigned "underflow" - yet it is discernible in the complete `§6.2.5 9` , which at first glance looks like underflow is not defined (hence UB), when it really is defined with an understanding of "reduced modulo". UV for a good answer. – chux - Reinstate Monica Feb 14 '17 at 15:37
  • Just read this http://stackoverflow.com/questions/18195715/why-is-unsigned-integer-overflow-defined-behavior-but-signed-integer-overflow-is (*cough* particularly the answer posted by yours faithfully *cough*) – Lundin Feb 14 '17 at 15:38
  • @chux I agree that reading/decoding the C standard isn't always an easy task. But if I were in that position, I'd read/verify the standard more keenly after the first comment (given that more than one person disagrees with it). Certainly wouldn't downvote before ascertaining my facts. Given that BigBobby hasn't responded, I'd presume he realized his mistake and all is well now. – P.P Feb 14 '17 at 16:29
2

It seems that you outputted the expression strlen(s)-strlen(x) using format specifier %u for example like this

printf( "%u\n", ( unsigned int )( strlen(s)-strlen(x)));
printf( "%u\n", c );

In this case the output is indeed is equal to

4294967294
4294967295

However if you output these expressions using casting to the type size_t and the format specifier %zu you will get

printf( "%zu\n", strlen(s)-strlen(x));
printf( "%zu\n", ( size_t ) c );

and

18446744073709551614
4294967295

So the value of expression strlen(s)-strlen(x) is greater than the value of the variable c casted to the type size_t.

You could get the expected by you result if sizeof( size_t ) would be equal to sizeof( unsigned int ).

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

This kind of implicit conversion from int / unsigned int to size_t type is error prone and difficult to detect. Static code analyzers like PVS-Studio are very good in finding such bugs automatically.

Ilya Ivanov
  • 123
  • 6
  • What implicit conversion? The only implicit conversion taking place here is `c` getting promoted to `size_t` in the expression `(strlen(s)-strlen(x))>c`, which is irrelevant to the result and the question. – Lundin Feb 14 '17 at 15:47
  • @Lundin Is not `unsigned int c = -1;` also an implied conversion of an `int` to `unsigned`? (which is also secondary to the crux of the post) – chux - Reinstate Monica Feb 14 '17 at 15:49
  • @chux Well yeah, but even if it was written as `-1u` it wouldn't affect the outcome. So this doesn't answer the question. – Lundin Feb 14 '17 at 15:52
  • Yes, I mean conversion in expression `(strlen(s)-strlen(x))>c`. It's better to make such conversions explicit to avoid unexpected results like in this question. – Ilya Ivanov Feb 15 '17 at 07:31