Thursday, February 26, 2009

Beauty of Computing : Memory, Addresses, and Pointers

Computers are interesting tools which can do a lot of things. They can add, subtract, multiply, divide, and do basically any type of mathematical calculation. One of the central parts of a computer is memory. You can think of a computer's memory as a gigantic row of boxes. Let's say there are 65,000 rows. Each row contains something.

For example, let's say row 1-100 contains your program. It is etched and stored in row 1-100. Each row contains an instruction like, ADD apple AND oranges STORE in NumberOfFruits. The very first instruction of your program is in row 1. The next instruction is in row 2 and so on until you get to row 100.

Row 101 to row 200 is were you store you can store your variables. The number of apples you have is stored in row 150, the number of oranges you have is stored in row 151, and the NumberOfFruits you have is stored in row 152.

Now, let's say we run our program one step at a time starting from row 1. The program does what row 1 says and then goes to row 2. The program does what row 2 says and going to row 25. At row 25, the program says to do the "Add Apple and Fruit" parts. In order to do this, the computer goes to row 150 and get's the number of apples and row 151 and gets the number of oranges. The computer does its thing and then stores the NumberOfFruits in row 152. Lucky for us, once this is done, row 26 tells the program to start over and read row 1 again and this continues on and on. So this program doesn't do much.

However, doesn't all these numbers make you confused? Let's say we do this. We'll call the row apples are in (150) "AppleRow", the row oranges are in (151) "OrangeRow", and the row NumberOfFruits are in (152) "NumberofFruitsRows". These are just nicknames for us so instead of always typing #150 or #152, we just type the name above. When we type the name above, we have the row location. Just for fun, let's also call where our "Add Apple and Fruit" (row 25) "AddAppleAndFruitFunctionRow".

Now, we can do lots of things. Not only can we see the number of items "Apple" but we can find the exact row something is in "AppleRow". We can even know the exact row our "Add Apple and Fruit" function is!!!! Once we have this knowledge, we can now move stuff around.

So, this is all I'll talk about here, but it will give you a start on memory, address, and pointers.

Oh yes, to help you out, replace any mention of the word "ROW" with "Address". Oh, and the name's we called things (AppleRow, OrangeRow, NumberofFruitsRows) you can call those pointers. As for the pointer to the function "Add Apple and Fruit", we'll just call that a functional pointer.

So I'll leave you with that. That wasn't so hard wasn't it? So where does the hard part come in? Oh you mean the absolutely horrible syntax some languages use *coughs* C *coughs. Those '*' and '&' can really hurt you if you aren't careful. Don't forget the funny jargon like dereference, pass by reference, reference.

As for the data types....we'll save that for another time if anyone wants to know more.

(Aside: Please note this is a very very simplified view of what's happening inside a computer. If you want to know more, I recommend looking up "Von Neumann Machine")

Tuesday, February 24, 2009

Virtual vs Override vs Regular Methods in C#

In the world of C#, one of the biggest FAQ is what is the difference between a method marked as override and a method marked marked as virtual. The answer to this question is actually 10x easier when you think about how C# works. C# works by an automated compiler known as the CLR (in .NET implementation) where things are decided at compile time (when you build a program) or at run time (when your program is actually running).

When you mark a method as virtual, you are telling the CLR that when you use that method, whatever object you are using at run-time is the method you should use.

For example, lets say you have a ClassA with a Virtual method called VirtMethod(). ClassB inherits from ClassA and has an Override method of the VirtMethod(). Because you marked ClassA as a virtual method, whenever you call VirtMethod(), the CLR waits until the actual code is executed to see if the VirtMethod() has been overridden by ClassB's VirtMethod().

ClassA MyClassA = new MyClassA();
ClassA MyClassB = new MyClassB();

MyClassA.VirtMethod(); //CLR sees that ClassA
virtual method is the only one there and thus
uses it.
MyClassB.VirtMethod(); //CLR notices that ClassB
has an override for ClassA. So it uses that.

For a regular method without anything behind it, the method you have at compile time is used. It doesn't matter what happens at run time. In fact, if you try an override a normal non-virtual method, a compile error will occur.

This is seen in 10.6.4 of the C# v 3.0 Specifications: "A compile-time error occurs unless all of the following are true for an override declaration:........The overridden base method is a virtual, abstract, or override method. In other words, the overridden base method cannot be static or non-virtual."

More information about the differences of the Virtual Method and the Override Method and a Plain Method can be found in section 10.6.3 - 10.6.4 of the C# v3.0 specifications. I highly recommend you all read that guide since it's very useful in telling you how things are suppose to work.

Monday, February 23, 2009

The Simple Block Bracket { } : How Scope Can Be Created

Local variables is one of the most powerful things in programming today. Although the concept is old, it is still one thing all programmers must keep in mind on how to use. Today, I'll talk about the stuff between the bracket ({}) called a block (also commonly called curly braces) and how it can allow you access to local variables. In C# you normally would write a function like this:

public void MyFunction()
{
Int64 MyVariable1 = 0;
Int64 MyVariable2 = 1;
}

As most of us knows, everything inside that function is locally scoped. That means only things inside MyFunction can access MyVariable1 & MyVariable2. Let's expand this.

public void MyFunction()
{
Int64 MyVariable1 = 0;
Int64 MyVariable2 = 1;
Int64 MyVariableChoice = 2;

if(MyVariableChoice)
{
Int64 MyVariable3 = 0;
}
else if(MyVariableChoice)
{
Int64 MyVariable3 = 1;
}
}

As most of us knows, MyVariable3 can only be accessed by statements inside the if(MyVariableChoice)block. Each instance of MyVariable3 is a local variable and memory is allocated for it's creation when the code reaches that block.


For most of us, all this is common sense. Let me rattle that common sense for a few programmers out there. Look at this switch statement:

public void MyFunction()
{

Int64 MyVariable1 = 1;
switch(MyVariable1)
{
case 1:
Int64 MyVariableCase = 1;
PrivateFunction(MyVariableCase);
break;
case 2:
Int64 MyVariableCase = 2;
PrivateFunction(MyVariableCase);
break;
default:
break;
}
}

If you try and compile this, you'll get an error. This is because a switch-case by itself doesn't allow for local variables. To make MyVariableCase a local variable, you need to surround it with a { } block so it looks like this.

Now let's change it a bit. Look at this switch statement:

public void MyFunction()
{

Int64 MyVariable1 = 1;
switch(MyVariable1)
{
case 1:
{
Int64 MyVariableCase = 1;
PrivateFunction(MyVariableCase);
}
break;
case 2:
{
Int64 MyVariableCase = 2;
PrivateFunction(MyVariableCase);
}
break;
default:
break;
}
}

This will compile and MyVariableCase will be defined as local variable. Noticed when I turned the free statements and put them inside a { } block, all the variables are now local. This is allowed by 5.1.7 of the C# Language Specifications v 3.0.

"A local variable is declared by a local-variable-declaration, which may occur in a block, a for-statement, a switch-statement or a using-statement; or by a foreach-statement or a specific-catch-clause for a try-statement." -5.1.7 Introduction

Now, before you go crazy with limiting local scope with blocks, remember, I only demonstrated this with C#. PLEASE read your language specification manual to make sure that your language supports scope by blocks. Highly popular languages such as Javascript DO NOT ALLOW LOCAL VARIABLES BY BLOCKS. Local variables in Javascript is allowed by functions but not blocks. Please don't try the case example above for Javascript. See Douglas Crockford's video on "The Javascript Programming Language" for more details.
 
Copyright 2008 - 2009 by WDO Enterprises LLC - All Rights Reserved