What Does i++ Really Mean? - c#

The question has been asked many times, "What's the difference between i++ and ++i". The accepted answer at What is the difference between i++ and ++i?, and I've seen this language in many other places as well, is that, "i++ means 'tell me the value of i, then increment', whereas ++i means 'increment i, then tell me the value'.
What confuses me is that I was not aware that we were discussing getting back a value for i in either scenario. I thought that i++ is syntactically equivalent to:
i = i + 1;
which is a statement, not an expression, so I don't understand where i is being returned at all.
Can you please expain what the statement actually means?
Thanks,

For reasons unknown to me, this old question with an accepted answer is attracting new answers today, many of which contain significant errors or omissions. Let me attempt to answer the question as asked definitively.
The question has been asked many times, "What's the difference between i++ and ++i". The accepted answer at [...], and I've seen this language in many other places as well, is that, "i++ means 'tell me the value of i, then increment', whereas ++i means 'increment i, then tell me the value'.
As I noted in my answer to that same question: this characterization is common and a reasonable first cut at understanding but unfortunately misleading when you look at the semantics more carefully. Please do not be misled by this vague and not entirely accurate characterization. Read my answer to that question instead.
What confuses me is that I was not aware that we were discussing getting back a value for i in either scenario. I thought that i++ is syntactically equivalent to i = i + 1; which is a statement, not an expression, so I don't understand where i is being returned at all.
You have a number of misunderstandings here. Rather than attack them all, let's just say what the truth is.
First, ++i and i++ are not syntactically exactly equivalent to anything. You cannot necessarily take a legal program that contains an ++i or an i++ and transform it solely syntactically into another legal program. So just banish that thought from your head. These are morally equivalent to increment-and-assign, and ought to be semantically equivalent, but there is not necessarily a syntactic desugaring that preserves program semantics or legality.
Let us now say some more true things. But first, some caveats. For the purposes of this discussion, the incremented expression i is a variable of type int, which can be evaluated either as a variable or a value without side effects, including exceptions. Moreover, we suppose that the incrementing operation does not produce an exception. And moreover we presume a single thread of execution. If you wish to know the semantics of increments and assignments in cases where evaluating the variable can throw, or produce another side effect, or is not a variable but rather is a property, or the operations are user-defined, or multiple threads are observing or mutating the variable, see the specification for details.
That said, here are some true facts:
++i, i++, and i = i + 1 are expressions
++i;, i++; and i = i + 1; are statements
The semantics of ++i are as follows:
temp1 is given the value of i
temp2 is given the value of temp1 + 1
i is given the value of temp2
the value of the expression is temp2
The semantics of i++ are as follows:
temp1 is given the value of i
temp2 is given the value of temp1 + 1
i is given the value of temp2
the value of the expression is temp1
Notice that the difference between the two forms is only what the value produced is. The steps that are taken to produce the side effect are identical in both cases. You are guaranteed in single-threaded C# that the side effect is observed complete before the value is produced.
The semantics of i = i + 1 are as follows:
temp1 is given the value of i
temp2 is given the value of temp1 + 1
i is given the value of temp2
the value of the expression is temp2
Notice that the semantics of i = i + 1 are identical to the semantics of ++i. This is not a guarantee that you can syntactically substitute i = i + 1 for ++i or vice versa, in an arbitrary program. In certain programs, this might be possible.
Notice that the semantics of i++ does not admit an "easy" semantically equivalent form. ((Func<int, int, int>)((int j, int k)=>j))(i, i=i+1) has the same semantics but is obviously a crazy thing to type.
The semantics of the statement forms of all three are:
Evaluate the expression as normal.
Discard the result.
Hopefully this definitively clears up any misunderstandings about what is an expression, what is a statement, what side effects and values are produced by the expressions, and in what order do they happen. Again, note that this explanation is narrowly targeted at simple cases involving integer variables without side effects on a single thread. For the details of how these operations work on other types, or interact with exceptions, or how they work in multithreaded programs, consult the C# specification or ask a more specific question.
Finally: I personally still find all this confusing, and I've been programming in C descendant languages for 30 years and I implemented these semantics in C#. If I find them confusing, and if almost every answer to every question I see on these operators contains significant errors or omissions, then we can safely conclude that these are confusing operators. As a result, I almost never use ++ or -- in my production code. I think it is bad style to have an expression that is useful for both its value and its side effects.
Try to find a way to structure your program so that ever statement has one side effect, and side-effecting expressions are limited to expression statements. Avoid ++, and particularly avoid any scenario where i++ and ++i would have different semantics, because that's a point where the program is going to be harder to understand and therefore harder to maintain correctly.

Edit: See Eric's answer, mine is meh.
You are right. The ++ is equivalent to i = i + 1, but the point to remember is that i = i + 1 is not only a statement, but can also be used as an expression:
Console.WriteLine((i = i + 1) * 42); // will inc i, and then print i*42
Console.WriteLine(++i * 42); // exactly same
Console.WriteLine(i++ * 42); // will inc i, and print old_i*42
Console.WriteLine((i++) * 42); // exactly same
So to conclude simply:
// this
int j = ++i * 42;
// behaves like
int j = (i = i + 1) * 42;
// but this
int j = i++ * 42;
// actually behaves like
int prev = i;
i = i + 1;
int j = prev * 42;

I think you may consider the following two functions to get an analogy to the i++ and ++i.
Fiddle
public static int IPlusPlus(ref int i) {
// simply increment i before returning it
i = i + 1;
return i;
}
public static int PlusPlusI(ref int i) {
// increment i only after you already returned it
try {
return i;
}
finally {
i = i + 1;
}
}
Just like function calls, i++ and ++i are right-hand-side expressions, meaning var a = i++; and var a = ++i; are valid statements. But i++ = 5; and ++i = 5; are not valid as that would use them as left-hand-side expressions.

Related

In C families, in a loop why is "less than or equal to" more preferred over just "less than" symbol? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 9 years ago.
Improve this question
Why is it that in C family of languages when we use a counter for any loop the most preferred comparison is Greater Equal To <= or its inverse? Please take a look at these three pieces of code
for (var i = 0; i <= 5; i++)
{...}/// loop1
for (var i = 0; i < 6; i++)
{...}/// loop2
for (var i = 0; i != 6; i++)
{...}/// loop3
I understand why loop 3 should be discouraged as something in code can assign i > 5 causing infinite loop. But loop1 and loop2 are essentially the same and loop2 may be better performance wise since only one comparison is done. So why is loop1 more preferred. Is it just convention or is there something more to it?
Note: I have no formal training in programming. i just picked up C when I needed better tools to program 8051s rather than using assembly language.
For loops are often used to iterate over arrays, and the limit is the length of the array. Since arrays are zero-based, the last valid element is length-1. So the choice is between:
for (int i = 0; i < length; i++)
and
for (int i = 0; i <= length-1; i++)
The first is simpler, so it is preferred. As a result, this idiom has become common even when the limit is not an array size.
We don't use != because occasionally we write loops where the index increments by variable steps, and sometimes it will skip over the limit. So it's safer to use a < comparison, so these won't turn into infinite loops.
This is generally a matter of contextual semantics, facilitating 'those that come after you' to maintain the code.
If you need 10 iterations of something, this is usually written as starting from 0 and having an end condition with < or != because it means the 10 is literally part of the code, thus showing clearly that 10 iterations were intended. The non-inclusive notation is also more practical for zero-based arrays like C-style strings. Notation with != is generally discouraged because it can cause endless loops in case the indexer isn't just a straightforward increment, unexpected overflows occur or the like.
On the other hand, if you need a loop from and to a specific value, it's also clearer if you have the end condition literally in the code, for example with for(var i = 1; i <= 5; i++) it is clear right away that it's an inclusive loop from 1 to 5.
These are just common reasons cited for using one notation or the other, most good programmers decide which to use by context and situation. There is no reason performance- or otherwise to prefer one over the other.
Less than or equal to is not preferred. Traditionally, in C,
less than was preferred; in C++, not equals is by far the most
idiomatic. Thus, in C:
#define N 100
int array[N];
for ( int i = 0; i < N; i ++ ) {
// ...
}
and in C++, either:
int const N = 100;
int array[N];
for ( int i = 0; i != N; ++ i ) {
// ...
}
or even more often, if there is only one container, and the
index isn't needed otherwise:
for ( int* p = std::begin( array ); p != std::end( array ); ++ p ) {
// ...
}
(In pre-C++11, of course, we used our own implementations of
begin and end to do the same thing.)
Other forms are generally not idiomatic, and are only used in
exceptional cases.
Almost all for loops have the exact same header except for the upper bound. It is a useful convention that helps with quick understanding and making less mistakes. (And the convention is <, not <=. Not sure where you got that from.)
Programs that do the same thing are not necessarily equal when it comes to code quality. Coding style has an objective component to it in that it helps humans deal with the complexity of the task.
Consistency is an important goal. If you have the choice, prefer the alternative that the majority of team members is using.

C# equivalent to Delphi High() and Low() functions for arrays that maintains performance?

In Delphi there are the Low() and High() functions that return the lowermost and uppermost index dimensions for an Array. This helps eliminate error prone for loops for iterating an array that might fall victim to an insidious +1/-1 array boundary error, like using <= when you meant < for the terminating condition in the for loop statement.
Here's an example for the Low/High functions (in Delphi):
for i := Low(ary) to High(ary) do
For now I'm using a simple for loop statement in C#:
for (int i = 0; i < ary.Length; i++)
I know there is the Array method GetDimension(N) but that has its own liabilities since I could introduce an error by accidentally using the wrong dimension index. I guess I could do something with enumerators, but I worry that there would be a significant performance cost when scanning a large array compared to using a for loop. Is there an equivalent to High/Low in C#?
The C# equivalent to the intrinsic low(ary) and high(ary) functions are, respectively, 0 and ary.Length-1. That's because C# arrays are zero based. I don't see any reason why the Length property of an array should have performance characteristics that differ from Delphi's high().
In terms of performance, the big difference between a Pascal for loop and that used by C derived languages concerns evaluation of the termination test. Consider a classic Pascal for loop:
for i := 0 to GetCount()-1 do
....
With a Pascal for loop, GetCount() is evaluated once only, at the beginning of the loop.
Now consider the equivalent in a C derived language:
for (int i=0; i<GetCount(); i++)
....
In this loop, GetCount() is evaluated every time round the loop. So in a language like C#, you would need a local variable to avoid calling that function over and over.
int N = GetCount();
for (int i=0; i<N; i++)
....
In the case of an array, if the optimiser could be certain that ary.Length did not mutate during the loop, then the code could be optimised by the compiler. I personally do not know whether or not the C# optimiser does that, but please refer to the comments for some more information.
Before you start re-writing your loops to use local variables containing the length of the array, check whether or not it makes any difference. Almost certainly it won't. The difference between Pascal and C-like for loops that I outline above is probably more significant in semantic terms than performance.
The language that I am particularly envious of is D. Here you can use a foreach loop that presents each item in an array as a reference, and thus allows you to modify the contents of the array:
void IncArray(int[] array, int increment) {
foreach (ref e; array) {
e += increment;
}
}
In C# the lower boundary is always zero, so the equivalent of Low(ary) is just 0.
For a single dimension array, the equivalent of High(ary) is ary.Length - 1. (For multi dimensional arrays you would need more than one loop anyway.)
Can you just use foreach statement instead?
like
foreach(int i in ary)
{
. . .
}
[Boundary(int Dimension)]
These boundary functions provide the start and end point for the user specified dimension of any array. A second dimension would be noted with a 1, instead of a zero, and so on.
for (int i = ary.GetLowerBound(0); i <= ary.GetUpperBound(0); i++ )
{}

Changing variables outside of Scope C#

I'm a beginner C# programmer, and to improve my skills I decided to give Project Euler a try. The first problem on the site asks you to find the sum of all the multiples of 3 and 5 under 1000. Since I'm essentially doing the same thing twice, I made a method to multiply a base number incrementally, and add the sum of all the answers togethor.
public static int SumOfMultiplication(int Base, int limit)
{
bool Escape = false;
for (int mult = 1; Escape == true; mult++)
{
int Number = 0;
int iSum = 0;
Number = Base * mult;
if (Number > limit)
return iSum;
else
iSum = iSum + Number;
}
regardless of what I put in for both parameters, it ALWAYS returns zero. I'm 99% sure it has something to do with the scope of the variables, but I have no clue how to fix it. All help is appreciated.
Thanks in advance,
Sam
Your loop never actually executes:
bool Escape = false;
for (int mult = 1; Escape == true; mult++)
Escape is set to false initially, so the first test fails (Escape == true returns false) and the body of the loop is skipped.
The compiler would have told you if you were trying to access variables outside of their defined scope, so that's not the problem. You are also missing a return statement, but that is probably a typo.
I would also note that your code never checks if the number to be added to the sum is actually a multiple of 3 or 5. There are other issues as well (for example, iSum is declared inside of the loop and initialized to 0 after each iteration), but I'll let you work that one out since this is practice. The debugger is your friend in cases like these :)
EDIT: If you need help with the actual logic I'll be happy to help, but I figure you want to work it out on your own if possible.
As others have pointed out, the problem is that the control flow does not do what you think it does. This is a common beginner problem.
My suggestion to you is learn how to use your debugger. Beginners often have this strange idea that they're not allowed to use tools to solve their coding problems; that rather, they have to reason out the defect in the program by simply reading it. Once the programs become more than a page long, that becomes impossible for humans. The debugger is your best friend, so get to know its features really well.
In this case if you'd stepped through the code in the debugger you'd see that the loop condition was being evaluated and then the loop was being skipped. At that point you wouldn't be asking "why does this return zero?", you'd be asking "why is the loop body always skipped?" Clearly that is a much more productive question to ask since that is actually the problem here.
Don't write any code without stepping through it in the debugger. Watch every variable, watch how it changes value (the debugger highlights variables in the watch windows right after they change value, by the way) and make sure that the control flow and the variable changes are exactly as you'd expect. Pay attention to quiet doubts; if anything seems out of the ordinary, track it down, and either learn why it is correct, or fix it until it is.
Regarding the actual problem: remember that 15, 30, 45, 60... are all multiples of both three and five, but you only want to add them to the sum once. My advice when solving Project Euler problems is to write code that is as like what you are trying to solve as is possible. Try writing the problem out in "pseudocode" first. I'd pseudocode this as:
sum = 0
for each positive number under 1000:
if number is multiple of three or five then:
add number to sum
Once you have that pseudocode you can notice its subtleties. Like, is 1000 included? Does the problem say "under 1000" or "up to 1000"? Make sure your loop condition considers that. And so on.
The closer the program reads like the problem actually being solved, the more likely it is to be correct.
It does not enter for loop because for condition is false.
Escape == true
returns false
Advice:
Using for loop is much simpler if you use condition as limit for breaking loop
for (int mult = 1; something < limit; mult++)
This way in most cases you do not need to check condition in loop
Most programming languages have have operator modulo division.
http://en.wikipedia.org/wiki/Modulo_operation
It might come handy whit this problem.
There are several problems with this code. The first, and most important, is that you are using the Escape variable only once. It is never set to false within your for loop, so it serves no purpose whatsoever. It should be removed. Second, isum is declared within your for loop, which means it will keep being re-initialized to 0 every time the loop executes. This means you will only get the last multiple, not the addition of all multiples. Here is a corrected code sample:
int iSum = 0;
for(int mult = 1; true; mult++)
{
int Number = Base * mult;
if(Number > limit)
return iSum;
else
iSum += Number;
}

Converting C# code to F# (if statement)

I'd like to know how to convert this code line by line from C# to F#. I am not looking to use any kind of F#'s idioms or something of the like. I am trying to understand how to map directly C#'s constructs to F#.
Here is the C# code:
//requires l.Length > 0
int GetMinimumValue(List<int> l) {
int minVal = l[0];
for (int i = 0; i < l.Length; ++i) {
if (l[i] > minValue) {
minVal = l[i];
}
}
return minVal;
}
And here is my F# attempt:
let getMinValue (l : int list) =
let minVal = l.Head
for i = 0 to (l.Length-1) do
if (l.Item(i) > minVal) then
minVal = col.Item(i)
minVal
Now, this ain't working. The problem seems to be related with the minVal = col.Item(i) line:
This expression was expected to have type unit but here has type bool
What is the problem, really?
If you want to convert it line by line then try the following
let getMinValue (l:System.Collections.Generic.List<int>) =
let mutable min = l.Item(0)
for i = 0 to (l.Count-1) do
if l.Item(i) < min then min <- l.Item(i)
min
Now as to why you're getting that particular error. Take a look at the following line
minVal = col.Item(i)
In F# this is not an assignment but a comparison. So this is an expression which produces a bool value but inside the for loop all expressions must be void/unit returning. Hence you receive an error.
Assignment in F# has at least 2 forms that I am aware of.
// Assigning to a mutable value
let mutable v1 = 42
v1 <- 13
// Assigning to a ref cell
let v1 = ref 0
v1 := 42
And of course, you should absolutely read Brian's article on this subject. It's very detailed and goes over many of the finer points on translating between the two languages
http://lorgonblog.spaces.live.com/Blog/cns!701679AD17B6D310!725.entry
There are a few problems with your literal translation. First of all, there's the immediate problem which causes the compiler error: as others have noted, let bindings are immutable by default. However, there's at least one other big problem: System.Collections.Generic.List<T> is very different from F#'s 't list. The BCL type is a mutable list backed by an array, which provides constant time random access to elements; the F# type is an immutable singly linked list, so accessing the nth element takes O(n) time. If you insist on doing expression-by-expression translation, you may find this blog post by Brian valuable.
I'd strongly recommend that you follow others' advice and try to acclimate yourself to thinking in idiomatic F# rather than literally translating C#. Here are some ways to write some related functions in F#:
// Given an F# list, find the minimum element:
let rec getMinList l =
| [] -> failwith "Can't take the minimum of an empty list"
| [x] -> x
| x::xs ->
let minRest = getMin xs
min x minRest
Note that this works on lists of any element type (with the caveat that the element type needs to be comparable from F#'s perspective or the application of the function will cause a compile-time error). If you want a version which will work on any type of sequence instead of just on lists, you could base it on the Seq.reduce function, which applies the function supplied as its first argument to each pair of elements in a sequence until a single value remains.
let getMin s = Seq.reduce min s
Or best of all, you can use the built-in Seq.min function, which is equivalent.
Short answer: = is not (mutable) assignment in F#.
Question: Do you really mean col?
Suggestions: Try to write this with NO assignments. There is recursion and built-in functions at your disposal :-)
You should read
What does this C# code look like in F#? (part one: expressions and statements)
I am disappointed that none of the other answers already linked it, because people ask the 'how to convert C# to F#' question a lot, and I have posted this answer link a lot, and by now some of the other answerers should know this :)
This is the most literal translation possible:
let getMinimumValue (l: List<int>) =
let mutable minVal = l.[0]
for i=0 to l.Length-1 do
if l.[i] > minVal then
minVal <- l.[i]
minVal

Comparing Doubles in Visual Studio - a standard way to catch this?

Even experienced programmers write C# code like this sometimes:
double x = 2.5;
double y = 3;
if (x + 0.5 == 3) {
// this will never be executed
}
Basically, it's common knowledge that two doubles (or floats) can never be precisely equal to each other, because of the way the computer handles floating point arithmetic.
The problem is, everyone sort-of knows this, but code like this is still all over the place. It's just so easy to overlook.
Questions for you:
How have you dealt with this in your development organization?
Is this such a common thing that the compiler should be checking that we all should be screaming really loud for VS2010 to include a compile-time warning if someone is comparing two doubles/floats?
UPDATE: Folks, thanks for the comments. I want to clarify that I most certainly understand that the code above is incorrect. Yes, you never want to == compare doubles and floats. Instead, you should use epsilon-based comparison. That's obvious. The real question here is "how do you pinpoint the problem", not "how do you solve the technical issue".
Floating point values certainly can be equal to each other, and in the case you've given they always will be equal. You should almost never compare for equality using equals, but you do need to understand why - and why the example you've shown isn't appropriate.
I don't think it's something the compiler should necessarily warn about, but you may want to see whether it's something FxCop can pick up on. I can't see it in the warning list, but it may be there somewhere...
Personally I'm reasonably confident that competent developers would be able to spot this in code review, but that does rely on you having a code review in place to start with. It also relies on your developers knowing when to use double and when to use decimal, which is something I've found often isn't the case...
static int _yes = 0;
static int _no = 0;
static void Main(string[] args)
{
for (int i = 0; i < 1000000; i++)
{
double x = 1;
double y = 2;
if (y - 1 == x)
{
_yes++;
}
else
{
_no++;
}
}
Console.WriteLine("Yes: " + _yes);
Console.WriteLine("No: " + _no);
Console.Read();
}
Output
Yes: 1000000
No: 0
In our organization we have a lot of financial calculations and we don't use float and double for such tasks. We use Decimal in .NET, BigDecimal in Java and Numeric in MSSQL to escape round-off errors.
This article describes the problem: What Every CS Should Know About floating-Point Arithmetic
If FxCop or similar (as Jon suggests) doesn't work out for you a more heavy handed approach might be to take a copy of the code - replace all instances of float or double with a class you've written that's somewhat similar to System.Double, except that you overload the == operator to generate a warning!
I don't know if this is feasible in practice as I've not tried it - but let us know if you do try :-)
Mono's Gendarme is an FxCop-like tool. It has a rule called AvoidFloatingPointEqualityRule under the Correctness category. You could try it to find instances of this error in your code. I haven't used it, but it should analyse regular .net dll's. The FxCop rule with the same name was removed long ago.

Categories

Resources