In a nice bit of synchronicity my article this week on Ask The Bug Guys, our continuing series on the Coverity Development Testing Blog, is about the differences between the C, C++ and C# interpretation of the `++`

operator[1. And of course everything in there applies equally well to the `--`

operator.] So read that first, and then it will make perfect sense why the increment operator on my `Natural`

class from last time is simply:

public static Natural operator ++(Natural x)
{
if (ReferenceEquals(x, null))
throw new ArgumentNullException("x");
return Add(x, One);
}

As always, if you have a question about a bug in a C, C++, C# or Java program please email it to TheBugGuys@coverity.com along with a concise reproducer of the problem if possible. We can’t answer every question but we’ll pick a sample of the most interesting ones a post an analysis on the dev testing blog.

**Next time on FAIC:** multiplication.

### Like this:

Like Loading...

*Related*

Interesting. Was it not Herb Sutter or maybe Scott Meyers who said that, in C/C++, you should always implement the postincrement operator in terms of the preincrement operator? Here’s a link – see the “The iterator increment uses postincrement” header:

http://herbsutter.com/2013/05/13/gotw-2-solution-temporary-objects/

I don’t think that changes anything, just interesting (to me) due to how the C# compiler handles it.

For those who ignore Eric Lippert’s stackoverflow posts, he wrote about C# increment in detail at http://stackoverflow.com/a/3346729/18192 (please note that the accepted answer is wrong).

Hm. So, if I want to implement finite field (say, base 2^32) arithmetics, I cannot have in-place increment, even if I implement field elements as structs?

Sure you can, you just shouldn’t abuse the operators for it.

People generally don’t expect that “x + 5” or “x++” changes the value of x and since C# doesn’t offer a += operator that would allow you to optimize for this case you’re probably better off with just implementing an add method.

To clarify: people expect that x++ changes *the variable x*, but that *variable* and the *object that is referred to* are not necessarily the same thing in C#.

Oh yes we have to be careful with semantics and definitions here. Certainly people expect x++ to change the value of the *variable* x, but just as you say not the object being pointed to.

“x = IntWrapper(5); foo(x++)” should still cause an IntWrapper(5) object being passed to foo after all (just making up a hopefully obvious example class).

And due to that expectation it’s just impossible to implement x++ in-place.

…and hope that the optimizer will eliminate redundant copying. Yeah. Good luck working with 10000-by-1000 matrices of 16 byte-sized values, because allocating 160 MB of memory at every addition is not cheap!

Since the built-in integer arithmetic *is* a finite field then clearly it can be implemented. I might get to finite fields at some point in this series.

(No, it’s not. It’s quotient ring $mathbb Z/2^32 mathbb Z$. 5 doesn’t have a multiplicative inverse in this ring.)

My maths is rusty, but in the ring/field/whatever of 32-bit signed integers -858993459 * 5 = 1. With unsigned integers 3435973837 * 5 = 1.

In both cases 5 does have a multiplicative inverse.

Wow, I am actually ashamed. Should’ve thought a bit before pointing at a random number and claiming it’s not invertible. Yes, of course 5 is a unit since 5 and 2^32 are coprime; but what about 2? Or any other natural power of two? Or any even number whatsoever? They divide zero (2 * 2^31 = 0, 10 * (-2147483648) = 0), and a zero divisor can’t have a multiplicative inverse (in associative rings at least).

So it’s still not a field, because half of the elements have no multiplicative inverse.

Someone else corrected me elsewhere about Z(compositeNumber) being a ring rather than a field, so it’s probably a common point of confusion. As for built-in integer types being finite ring, that’s mostly true in C# unchecked numeric contexts, but not quite. In situations involving type conversions, C# often regards them as numbers. Personally, I think a lot of numeric-handling confusion would be best avoided by having separate storage-location types for integers that behave as numbers and ones that behave as rings; an operation between a number and a ring element would yield an element of that same ring, as would an operation between two operands of matching ring types. Operations between mismatched ring operands should be forbidden (unless one of the elements is converted to a number). Such a thing could probably be added to .NET languages without affecting the runtime by defining attributes that could be applied to public members to indicate how compilers should interpret them [e.g. regardless of whether checked arithmetic is enabled, if a function has an `int` return type explicitly tagged as a number and it returns -2000000000, subtracting 1000000000 from it should throw an OverflowException; if it were tagged as a ring member, it should yield -852516352]. There would be no need for separate .NET types to define the “number” and “ring” variants of each integer type, since one can’t perform any arithmetic upon boxed or generic integer types without first converting them to known integer types.

Couple of small typos on the throw line:

throw new NullArgumentException(x);

should be:

throw new ArgumentNullException(“x”);

Ask The Bug Guys is no longer available on the Coverity site, but an archived version of the linked article can be found at https://web.archive.org/web/20160618054531/http://blog.coverity.com/2013/09/24/increment-semantics/

Thanks; I’m eventually going to track those all down on the wayback machine and re-post them here.

👍

Pingback: C#学习教程：C＃postfix和前缀增量/减量重载差异分享-安普网