1. ## Who is right?

Code:
```	ULONGLONG ll1 = 50000ull;
LONGLONG ll2  = 99000ll;
LONGLONG ll3;

if ((ll1 - ll2) < 0) printf("< 0\n");
else printf("> 0\n");

ll3 = ll1 - ll2;
if (ll3 < 0) printf("< 0\n");
else printf("> 0\n");```
MSVC Output:
> 0
< 0
Lcc Output:
< 0
< 0
Who is right here, or is it undefined?

EDIT: :-; Fixed. I don't have an entry function either.

2. Neither of them are right. You don't actually have a variable called ll in your example. It won't compile.

Quzah.

3. I'll ignore the fact that your code won't compile.

>Who is right here, or is it undefined?
Conversion of arithmetic types can be complicated.

>(ll - ll2)
As an expression, the usual conversions apply, and the type of the result is the type of the longest, floatiest operand. So the result of this expression will be unsigned long long. Because unsigned types roll over when they reach their boundaries, the result of this expression is a very large unsigned value, thus, greater than 0.

>ll3 = ll - ll2;
This is completely different from the above. Note that the right hand side of the expression is the same as above, but explicit assignment to a signed type is considered an overflow and is technically undefined even though a lot of programs rely on a quiet conversion that results in a negative number. So a reasonable result would be less than 0, but since it is undefined behavior, you can't rely on that.

4. I'll ignore the fact that your code won't compile.
While we're at it, types are undefined too!

As an expression, the usual conversions apply, and the type of the result is the type of the longest, floatiest operand. So the result of this expression will be unsigned long long. Because unsigned types roll over when they reach their boundaries, the result of this expression is a very large unsigned value, thus, greater than 0.

This is what I figured. So LCC is wrong.

This is completely different from the above. Note that the right hand side of the expression is the same as above, but explicit assignment to a signed type is considered an overflow and is technically undefined even though a lot of programs rely on a quiet conversion that results in a negative number. So a reasonable result would be less than 0, but since it is undefined behavior, you can't rely on that.

So is there any 'correct' way to get a signed result from an unsigned operation.

5. Originally posted by anonytmouse

This is what I figured. So LCC is wrong.
No. That's the thing with 'undefined'. There is no "wrong". It simply is undefined. That means they could make it output "This is right!" to a new file called "undefined.txt" whenver this situation occurred, and it wouldn't be "wrong". It's undefined. It can be anything. It can do anything. There is no wrong. It simply has no defined reaction to said situation. Thus the compiler maker can do whatever they feel like and still have a fully ANSI compatible compiler.

Originally posted by anonytmouse
So is there any 'correct' way to get a signed result from an unsigned operation.
That depends. What do you define as "correct"? Do you want it to wrap around? Do you want it to be zero if it isn't accurate? Or what? There is no correct. You could do something like:
Code:
```signed int signme( unsigned int i )
{
if( i < maximum_unsigned_value / 2 )
return (signed int) i;
else
return -1;
}```
-1 being an error. Or, you could then instead subtract 1/2 maximum unsigned value from i and then subtract the remainder of that from zero. Or... See the problem with undefined behavior?

Quzah.

6. >So is there any 'correct' way to get a signed result from an unsigned operation.
Unless the result has a valid signed representation, no. In other words:
Code:
```unsigned long l1 = 100UL;
unsigned long l2 = 50UL;
long l3;

l3 = l1 - l2;```
The result is an unsigned value (50), but when converted to a signed value, the representation is the same. So the above expression is legal and well defined. However, if you reverse the expression:
Code:
```unsigned long l1 = 100UL;
unsigned long l2 = 50UL;
long l3;

l3 = l2 - l1;```
The result is an unsigned value (4294967246 on my machine), but this is outside of the boundaries for a signed long, so overflow occurs and the result is undefined.

7. So wrapping is defined behavior, but conversion isn't?

8. >So wrapping is defined behavior, but conversion isn't?
Unsigned wrapping is defined behavior, but signed overflow is not. As I said, conversions can be complicated.

9. No. That's the thing with 'undefined'. There is no "wrong". It simply is undefined.

Can I just clarify what exactly is undefined here? Am I correct in saying that in the context of the operation it is defined that both values are treated as unsigned and that the undefined part is what to do with the overflow?

Unless the result has a valid signed representation, no.

So if we want to reliably and portably get a signed result we must, in theory, use signed values.

So we change:
Code:
```short = ushort - ushort
/* to: */
long = long - long```
The trouble is using long long we don't have that option.

Code:
```	ll3 = ll1 - ll2;
if (ll3 < 0) printf("< 0\n");
else printf("> 0\n");```
In practise, on the Windows platform, will this always give the 'correct'(as in the real world) result (where ll2 is less than signed_long_long_max)? I don't seem to have much choice.

Thanks.

10. If your compiler documents its behavior, you can use it. But don't forget that your app is not portable anymore.

11. But don't forget that your app is not portable anymore.

In theory, but I'm wondering if there is a Windows compiler with differing behaviour for this example.

Someone could have a useful website documenting these behaviours.

12. >Someone could have a useful website documenting these behaviours.
Wouldn't that be an exercise in futility.

13. > if ((ll1 - ll2) < 0) printf("< 0\n");

The question is: which operand gets converted before the subtraction is performed? Is ll1 converted to a LONGLONG, or is ll2 converted to a ULONGLONG?

If ULONGLONG - ULONGLONG, then MSVC is right, as the result has to be unsigned.
If LONGLONG - LONGLONG, then Lcc is right (assuming LONGLONG is signed).

Does the C standard say what conversion occurs before the subtraction, or is it up to the compiler?

14. > Does the C standard say what conversion occurs before the subtraction, or is it up to the compiler?
It's specified by the standard
Also K&R2 Page 198 Para A.6 also explains it

15. >It's specified by the standard
>Also K&R2 Page 198 Para A.6 also explains it

Quoting from the draft:
From 6.3.1.1
— The rank of any unsigned integer type shall equal the rank of the corresponding
signed integer type, if any.
From 6.3.1.8
If both operands have the same type, then no further conversion is needed.

Otherwise, if both operands have signed integer types or both have unsigned
integer types, the operand with the type of lesser integer conversion rank is
converted to the type of the operand with greater rank.

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.
From what I can tell, MSVC is right. But I may have misinterpreted what I read.