Author Topic: postfix and prefix incrementing  (Read 13809 times)

0 Members and 1 Guest are viewing this topic.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
postfix and prefix incrementing
« on: February 02, 2006, 03:48:24 AM »
Bronson is autistic and has cerebral palsy. Consequently he has a fascination with numbers and likes an ordered existence.

Today I was trying to explain the logic of a for loop.

Things were fine till we got to postfix and prefix incrementing.

I ended up using this to help explain the difference.

So ... just in case anyone else has wondered ...
Code: [Select]
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication_PostAndPrefix
{
    class Program
    {
        static void Main(string[] args)
        {
            int xValue, n, p;
            //
            Console.WriteLine("Postfix++ and ++Prefix Examples for Shorty");

            xValue = 100;
            Console.WriteLine("xValue is {0}" , xValue.ToString());
            Console.WriteLine("----------------");

            xValue = 100;
            Console.WriteLine("xValue is {0}", xValue.ToString());
            Console.WriteLine("Postfix++ uses the current value, then adds 1 and saves.");
            Console.WriteLine("xValue++ is {0}", (xValue++).ToString());
            Console.WriteLine("xValue is {0}", xValue.ToString());
            Console.WriteLine("----------------");

            xValue = 100;
            Console.WriteLine("xValue is {0}", xValue.ToString());
            Console.WriteLine("++Prefix adds 1 and saves, then uses the new value.");
            Console.WriteLine("++xValue is {0}", (++xValue).ToString());
            Console.WriteLine("xValue is {0}", xValue.ToString());
            Console.WriteLine("----------------");

            n = 1;
            p = ++n;
            Console.WriteLine("n = 1;  p = ++n;");
            Console.WriteLine("n is {0}, p is {1}", n.ToString(), p.ToString() );
            Console.WriteLine("----------------");

            n = 1;
            p = n++;
            Console.WriteLine("n = 1;  p = n++;");
            Console.WriteLine("n is {0}, p is {1}", n.ToString(), p.ToString());

        }
    }
}

/*

Postfix++ and ++Prefix Examples for Shorty
xValue is 100
----------------
xValue is 100
Postfix++ uses the current value, then adds 1 and saves.
xValue++ is 100
xValue is 101
----------------
xValue is 100
++Prefix adds 1 and saves, then uses the new value.
++xValue is 101
xValue is 101
----------------
n = 1;  p = ++n;
n is 2, p is 2
----------------
n = 1;  p = n++;
n is 2, p is 1
Press any key to continue . . .

*/

added : n and p variable calcs added for clarification
« Last Edit: February 02, 2006, 09:49:12 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #1 on: February 02, 2006, 04:16:31 AM »
Probably should post this too 'cause it's sort-of relevent .. The For Loop stuff ..
Code: [Select]
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication_ForLoops
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] nameArray = { "zero", "one", "two", "three", "four" };
            Console.WriteLine("nameArray.Length : {0}", nameArray.Length.ToString());

            for (int index = 0; index < nameArray.Length; ++index) {
                Console.Write("Index {0} : ", index.ToString());
                Console.WriteLine(nameArray[index]);
            }
        }
    }
}
/*
nameArray.Length : 5
Index 0 : zero
Index 1 : one
Index 2 : two
Index 3 : three
Index 4 : four
Press any key to continue . . .
*/

modified :  incrementer index++)  changed to ++index)
« Last Edit: February 02, 2006, 10:11:14 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

HD

  • Guest
Re: postfix and prefix incrementing
« Reply #2 on: February 02, 2006, 08:30:22 AM »
Since I have never been a fulltime C, C++, or C# programmer I have always had to go back and "hit" the book / on-line documentation everytime I wanted to use the increment / decrement operators. It use to frustrate me that I couldn't remember something so simple.

When I saw this post I had to respond because one of my C# reference books (C# For Dummies) included the history of these operators. I stashed this history away because I remember hearing a college instructor saying, "Industry won't consider you to be a true C programmer unless you use pointers and the increment / decrement operators."

After reading the history of the increment / decrement operators, if Bronson feels more comfortable using the longer but more intuitive notation -- he should go for it.


History of the increment / decrement operators:

Why have an increment operator, and why two of them?
The reason for the increment operator lies in the obscure fact that the PDP-8 computer of the 1970’s had an increment instruction. This would be of little interest today were it not for the fact that the C language, the original precursor to C#, was originally written for the PDP-8. Because that machine had an increment instruction, n++ generated fewer machine instructions than n = n + 1. As slow as those machines were, saving a few machine instructions was a big deal.
 
Today, compilers are smarter and there’s no difference in the execution time for n++ and n = n + 1 so the need for the increment operator has gone away. However, programmers are creatures of habit, and the operator remains to this day. You almost never a C++ programmer increment a value using the longer but more intuitive n = n + 1. Instead, you see the increment operator.
 
Further, when standing by itself (that is, not part of a larger expression), the post-increment operator almost always appears instead of the pre-increment. There’s no reason other than habit and the fact that it looks cooler.
 
C# actually has has two increment operators: ++n and n++ The first one, ++n, is called the preincrement operator, while n++ is the postincrement, The difference is subtle but important.
 
int n;
n = 1;
int o = ++n; // the value of o is 2. ++n is the value of n after being incremented.
 
n = 1;
int m = n++ the // the value of m is 1. n++ is the value of n before it is incremented.
 
Either way, the resulting value value of n is 2.
 
Equivalent decrement operators - that is, n-- and --n - exist to replace n = n -1. These work in exactly the same way as the increment operators.

Chuck Gabriel

  • Guest
Re: postfix and prefix incrementing
« Reply #3 on: February 02, 2006, 08:50:52 AM »
It is worth noting that unless you intend to use the return value of the increment AND it needs to reflect the pre-increment value, you should use the prefix increment because it is more efficient.

Postfix increment has to store the current value in a temporary location, then increment the original, then return the temporary.  Prefix increment just increments the value in place and returns it.

Of course, the difference is trivial for integral types, but it can become an issue when dealing with objects (think iterators) that have prefix and postfix increment operators, or when dealing with long loops, so it is a good habit to get into.

Having said all that, I think the real issue here is "who is Bronson?"

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #4 on: February 02, 2006, 09:07:28 AM »
Interesting History Nick.

Quote
It is worth noting that unless you intend to use the return value of the increment AND it needs to reflect the pre-increment value, you should use the prefix increment because it is more efficient.

Good point chuck, the joy is in the details, heh.

Bronson is my nephew, who's been living with us most of his life. Gentle soul. Not rainmanish exactly, but has an intimate knowledge of bus timetables.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Chuck Gabriel

  • Guest
Re: postfix and prefix incrementing
« Reply #5 on: February 02, 2006, 09:15:12 AM »
Thanks for sharing that.

You're a good man Kerry Brown.

Draftek

  • Guest
Re: postfix and prefix incrementing
« Reply #6 on: February 02, 2006, 09:32:29 AM »
Ditto,

Thanks for sharing the example and the info.

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: postfix and prefix incrementing
« Reply #7 on: February 02, 2006, 10:10:28 AM »
Quote
It is worth noting that unless you intend to use the return value of the increment AND it needs to reflect the pre-increment value, you should use the prefix increment because it is more efficient.
I thought I read the exact opposite.  I will have to look that up if I can find it
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #8 on: February 02, 2006, 10:18:57 AM »
Hi David,

The ++index is not evaluated untill the for loop runs once.
On the second pass the index is incremented and then the conditional test is performed.

I had to step it through the debugger to make sure too :-)
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Chuck Gabriel

  • Guest

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #10 on: February 02, 2006, 10:50:34 AM »
Usefull site Chuck .. linked as a keeper.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #11 on: February 05, 2006, 04:26:32 AM »
I didn't have enough time to finish my investigation of this, so I'll just pop it up and see if anyone wants to make a qualified < or otherwise :-) > comment.

This code ;
Code: [Select]
        public int preInctement()
        {
            int result = 1;
            int tempVal = 1;
            result = ++tempVal;

            return result;
        }
        public int postInctement()
        {
            int result = 1;
            int tempVal = 1;
            result = tempVal++;

            return result;
        }
Produces this IL <Intermediate Language> code when run through the ILDASM Disassembler.
Code: [Select]
.method public hidebysig instance int32  preInctement() cil managed
{
  // Code size       17 (0x11)
  .maxstack  2
  .locals init ([0] int32 result,
           [1] int32 tempVal,
           [2] int32 CS$1$0000)
  .language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'L:\VisualStudio2005\Projects\2229\ConsoleApplication-PostAndPrefix\ConsoleApplication-PostAndPrefix\Program.cs'
//000045:         {
  IL_0000:  nop
//000046:             int result = 1;
  IL_0001:  ldc.i4.1
  IL_0002:  stloc.0
//000047:             int tempVal = 1;
  IL_0003:  ldc.i4.1
  IL_0004:  stloc.1
//000048:             result = ++tempVal;
  IL_0005:  ldloc.1
  IL_0006:  ldc.i4.1
  IL_0007:  add
  IL_0008:  dup
  IL_0009:  stloc.1
  IL_000a:  stloc.0
//000049:
//000050:             return result;
  IL_000b:  ldloc.0
  IL_000c:  stloc.2
  IL_000d:  br.s       IL_000f
//000051:         }
  IL_000f:  ldloc.2
  IL_0010:  ret
} // end of method Program::preInctement


.method public hidebysig instance int32  postInctement() cil managed
{
  // Code size       17 (0x11)
  .maxstack  3
  .locals init ([0] int32 result,
           [1] int32 tempVal,
           [2] int32 CS$1$0000)
  .language '{3F5162F8-07C6-11D3-9053-00C04FA302A1}', '{994B45C4-E6E9-11D2-903F-00C04FA302A1}', '{5A869D0B-6611-11D3-BD2A-0000F80849BD}'
// Source File 'L:\VisualStudio2005\Projects\2229\ConsoleApplication-PostAndPrefix\ConsoleApplication-PostAndPrefix\Program.cs'
//000053:         {
  IL_0000:  nop
//000054:             int result = 1;
  IL_0001:  ldc.i4.1
  IL_0002:  stloc.0
//000055:             int tempVal = 1;
  IL_0003:  ldc.i4.1
  IL_0004:  stloc.1
//000056:             result = tempVal++;
  IL_0005:  ldloc.1
  IL_0006:  dup
  IL_0007:  ldc.i4.1
  IL_0008:  add
  IL_0009:  stloc.1
  IL_000a:  stloc.0
//000057:
//000058:             return result;
  IL_000b:  ldloc.0
  IL_000c:  stloc.2
  IL_000d:  br.s       IL_000f
//000059:         }
  IL_000f:  ldloc.2
  IL_0010:  ret
} // end of method Program::postInctement




There seems to be the same number of instructions, BUT notice the .maxstack allowance ;
... the postInctement() method expects to use 3 stack slots while preInctement() expects to use 2.

These are indicated in the code by ldc.i4.1 which is used to push value<s> onto the stack, ie save them for later use
The anomolie is that BOTH methods actually use  ldc.i4.1 3 times, irrespective of the .maxstack allowance.

weird, heh ..

Has anyone passing by done any study regarding the resulting IL code.

Have a good week ...

« Last Edit: February 05, 2006, 04:36:37 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: postfix and prefix incrementing
« Reply #12 on: February 05, 2006, 07:54:19 PM »
For those interested in deciphering the above MSIL (Microsoft Intermediate Language), here is a brief intro and tutorial by Kenny Kerr -> http://weblogs.asp.net/kennykerr/category/7140.aspx
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

MickD

  • King Gator
  • Posts: 3619
  • (x-in)->[process]->(y-out) ... simples!
Re: postfix and prefix incrementing
« Reply #13 on: February 05, 2006, 08:48:13 PM »

There seems to be the same number of instructions, BUT notice the .maxstack allowance ;
... the postInctement() method expects to use 3 stack slots while preInctement() expects to use 2.

These are indicated in the code by ldc.i4.1 which is used to push value<s> onto the stack, ie save them for later use
The anomolie is that BOTH methods actually use ldc.i4.1 3 times, irrespective of the .maxstack allowance.

weird, heh ..

Has anyone passing by done any study regarding the resulting IL code.

Have a good week ...



After a quick study the second function pushes 1 item then 'dup' s (duplicates) the top item on the stack(another push), then pushes another item on the stack giving you 3 items before the add instruction whereas the first section only has 2 pushes before the add instruction.

++i code with comments
Code: [Select]
  IL_0005:  ldloc.1      //1st push
  IL_0006:  ldc.i4.1     //2nd push
  IL_0007:  add          //pop 2, add and push result, total stack = 1
  IL_0008:  dup         //pop the top (stack=0)and duplicate, push original and copy = 2 pushes, stack = 2
  IL_0009:  stloc.1      //pop 1
  IL_000a:  stloc.0      //pop 2, stack = 0( balanced)

i++ code with comments
Code: [Select]
  IL_0005:  ldloc.1     //push 1
  IL_0006:  dup         //pop 1 and push 2, stack = 2
  IL_0007:  ldc.i4.1    //push another, stack now = 3
  IL_0008:  add         //pop 2, add and push result, stack = 2
  IL_0009:  stloc.1     //pop 1
  IL_000a:  stloc.0     //pop 2, stack = 0 (balanced)
"Short cuts make long delays,' argued Pippin.”
J.R.R. Tolkien

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: postfix and prefix incrementing
« Reply #14 on: February 05, 2006, 08:57:16 PM »
From a further look this morning, I think that IS the case Mick.

I was originally considering instructions only, not net maximum usage allocation.

Thanks for having a play ..
« Last Edit: February 05, 2006, 09:13:34 PM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.