简体   繁体   中英

When does ++ not produce the same results as +1?

The following two C# code snippets produce different results (assuming the variable level is used both before and after the recursive call). Why?

public DoStuff(int level)
{
  // ...
  DoStuff(level++);
  // ...
}

,

public DoStuff(int level)
{
  // ...
  DoStuff(level+1);
  // ...
}

After reading some of the responses below I thought it would be worthwhile posting the stack traces for level++, ++level and level+1 to highlight how deceiving this problem is.

I've simplified them for this post. The recursive call sequence starts with DoStuff(1).

// level++

DoStuff(int level = 1)
DoStuff(int level = 2)
DoStuff(int level = 2)
DoStuff(int level = 2)

// ++level

DoStuff(int level = 4)
DoStuff(int level = 4)
DoStuff(int level = 3)
DoStuff(int level = 2)

// level+1

DoStuff(int level = 4)
DoStuff(int level = 3)
DoStuff(int level = 2)
DoStuff(int level = 1)

To clarify all the other responses:

+++++++++++++++++++++

DoStuff(a++);

Is equivalent to:

DoStuff(a);
a = a + 1;

+++++++++++++++++++++

DoStuff(++a);

Is equivalent to:

a = a + 1;
DoStuff(a);

+++++++++++++++++++++

DoStuff(a + 1);

Is equivalent to:

b = a + 1;
DoStuff(b);

+++++++++++++++++++++

Because the first example is really equivalent to:

public DoStuff(int level)
{  
  // ...
  int temp = level;
  level = level + 1;
  DoStuff(temp);
  // ...
}

Note that you can also write ++level; that would be equivalent to:

public DoStuff(int level)
{  
  // ...
  level = level + 1;
  DoStuff(level);
  // ...
}

It's best not to overuse the ++ and -- operators in my opinion; it quickly gets confusing and/or undefined what's really happening, and modern C++ compilers don't generate more efficient code with these operators anyway.

level++ will pass level into DoStuff and then increment level for use in the rest of the function. This could be a fairly nasty bug as the recursion will never end (from what is shown DoStuff is always being passed the same value). Perhaps ++level is meant instead, as this is the opposite of level++ (increments level and passes the incremented value into DoStuff )?

level+1 will pass level+1 into DoStuff and leave level unchanged for the rest of the function.

the return value of level++ will be level and therefore pass level into DoStuff . This could be a fairly nasty bug as the recursion will never end (from what is shown DoStuff is always being passed with the same value). Perhaps ++level or level + 1 is meant instead?

level + 1 will pass level + 1 into DoStuff and leave level unchanged for the rest of the function.


The post-increment operator (variable++) is precisely equivalent to the function

int post_increment(ref int value)
{
    int temp = value;
    value = value + 1
    return temp;
}

while the pre-increment operator (++variable) is precisely equivalent to the function

int pre_increment(ref int value)
{
    value = value + 1;
    return value;
}

Therefore, if you expand the operator inline into the code, the operators are equivalent to:

DoStuff(a + 1)

int temp = a + 1;
DoStuff(temp);

DoStuff(++a)

a = a + 1;
DoStuff(a);

DoStuff(a++);

int temp = a;
a = a + 1;
DoStuff(temp);

It is important to note that post-increment is not equivalent to:

DoStuff(a);
a = a + 1;

Additionally, as a point of style, one shouldn't increment a value unless the intention is to use the incremented value (a specific version of the rule, "don't assign a value to a variable unless you plan on using that value"). If the value i + 1 is never used again, then the preferred usage should be DoStuff(i + 1) and not DoStuff(++i) .

The first is using the value in level and THEN incrmenting it.

The latter is using level+1 as a passed variable.

level++ returns the current value of level , then increments level . level+1 doesn't change level at all, but DoStuff is called with the value of (level + 1) .

public DoStuff(int level)
{

  // DoStuff(level);
  DoStuff(level++);
  // level = level + 1;
  // here, level's value is 1 greater than when it came in
}

It actually increments the value of level.

public DoStuff(int level)
{
  // int iTmp = level + 1;
  // DoStuff(iTmp);
  DoStuff(level+1);
  // here, level's value hasn't changed
}

doesn't actually increment the value of level.

Not a huge problem before the function call, but after the function call, the values will be different.

In level++ you are using postfix operator. This operator works after the variable is used. That is after it is put on the stack for the called function, it is incremented. On the other hand level + 1 is simple mathematical expression and it is evaluated and the result is passed to called function. If you want to increment the variable first and then pass it to called function, you can use prefix operator: ++level

The first code snippet uses the post-operation increment operator, so the call is made as DoStuff(level);. If you want to use an increment operator here, use DoStuff(++level);.

level+1 sends whatever level+1 is to the function. level++ sends level to the function and then increments it.

You could do ++level and that would likely give you the results you want.

The first example uses the value of 'index', increments the value and updates 'index'.

The second example uses the value of 'index' plus 1 but does not change the content of 'index'.

So, depending on what you are wanting to do here, there could be some surprises in store!

Whilst it is tempting to rewrite as:

DoStuff(++level);

I personally think this is less readable than incrementing the variable prior to the method call. As noted by a couple of the answers above, the following would be clearer:

level++;
DoStuff(level);

When you use a language that allows operator overloading, and '+ <integer>' has been defined to do something other than post- and prefix '++'.

Then again, I have only seen such abominations in school projects*, if you encounter that in the wild you probably have a really good, well-documented, reason.

[* a stack of integers, if I'm not mistaken. '++' and '--' pushed and popped, while '+' and '-' performed normal arithmetics]

To put it in the most simple way, ++var is a prefix operator and will increment the variables before the rest of the expression is evaluated. var++ , a postfix operator, increments a variable after the rest of the expression is evaluated. And as others have mentioned of course, var+1 creates just a temporary variable (seperate in memory) which is initiated with var and incremented with constant 1 .

As far as my experience goes, the parameter expression is evaluated first, and gets a value of level. The variable itself is incremented before the function is called, because the compiler doesnt care whether you are using the expression as a parameter or otherwise... All it knows is that it should increment the value and get the old value as the result of the expression.

However in my opinion, code like this is really sloppy, since by trying to be clever, it makes you have to think twice about what is really happening.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM