some bits flipped
some bits flipped

Reputation: 3092

C# 0 (minus) uint = unsigned result?

public void Foo(double d){
    // when called below, d == 2^32-1 
    ...
}
public void Bar(){
    uint ui = 1;
    Foo( 0 - ui );
}

I would expect both 0 and ui to be promoted to signed longs here.

True, with the 0 literal it is knowable at compile time that a cast to uint is safe,

but I suppose this all just seems wrong. At least a warning should be issued.

Thanks!

Does the language spec cover a semi-ambiguous case like this?

Upvotes: 4

Views: 4263

Answers (3)

Jon Skeet
Jon Skeet

Reputation: 1502126

Why would anything be promoted to long? The spec (section 7.8.5) lists four operators for integer subtraction:

  • int operator-(int x, int y);
  • uint operator-(uint x, uint y);
  • long operator-(long x, long y);
  • ulong operator-(ulong x, ulong y);

Given that the constant value 0 is implicitly convertible to uint, but the uint value ui is not implicitly convertible to int, the second operator is chosen according to the binary operator overload resolution steps described in section 7.3.4.

(Is it possible that you were unaware of the implicit constant expression conversion from 0 to uint and that that was the confusing part? See section 6.1.9 of the C# 4 spec for details.)

Following section 7.3.4 (which then refers to 7.3.5, and 7.5.3) is slightly tortuous, but I believe it's well-defined, and not at all ambiguous.

If it's the overflow that bother you, would expect this to fail as well?

int x = 10;
int y = int.MaxValue - 5;
int z = x + y;

If not, what's really the difference here?

Upvotes: 7

NominSim
NominSim

Reputation: 8511

In a checked context, if the difference is outside the range of the result type, a System.OverflowException is thrown. In an unchecked context, overflows are not reported and any significant high-order bits outside the range of the result type are discarded.

http://msdn.microsoft.com/en-us/library/aa691376(v=vs.71).aspx

Technically, doing the following:

double d = checked(0-ui);

Will result in a throw of System.OverflowException which is perhaps what you are expecting, but according to the spec since this is not checked the overflow is not reported.

Upvotes: 0

SiliconMind
SiliconMind

Reputation: 2179

It's the int that is being cast to uint to perform substraction from 0 (which is implicitly interpreted by the compiler as uint). Note that int to uint is an implicit conversion hence no warning. There is nothing wrong with your code... except that uint is not CLS-compilant. You can read why here. More info on CLS-compilant code on MSDN

Upvotes: 0

Related Questions