Wednesday, July 13, 2011

Coding Lessons: C and variables (lesson 2)

Ok, so in the last lesson we looked at setting up a program, the header files that you needed to include to be able to accept and output data, comments, outputting data and how to compile the program to an executable.

The trouble is, that program didn't really do much, it doesn't accept any data, doesn't processes anything and the output is pretty much always the same boring message.

So, lets have a look as some variables,

Variables come in different shapes and sizes, there are integers, chars, floating point numbers and strings.

In general these can be modified with some special words, and those special words either shorten or lengthen the bits assigned to the variable, The amount of data assigned to a variable? who the hell cares about that? Well on a PC, you'd pretty much be right, there is no drive these days to write efficient code like there used to be, drive space, memory space and processor speed are all available in abundance, But, as I said in lesson 1, these lessons are gearing up for switching away from the PC to programming micro controllers where not doings efficiently can quickly lead to your program running well frankly badly, or lead to you running out of memory, that's either memory on the device for your program to be held in, or memory in RAM for data to be stored in as the program is running.

Data Types
So lets go through the different data types.
I said earlier that there were basically 4 data types (ints, chars, floats and strings).

There are several modifiers for these data types (const, signed, unsigned, short and long) and those modifiers pretty much do exactly what they say on the tin.

If you write const before declaring an integer for example, then you are saying that variable is constant, it can't change,

const int lesson=2;

That variable (called lesson) is now constant.

This is probably going to be difficult to explain without going in depth into how numbers are represented on a computer. So this lesson has to deviate away from C for a moment and into Binary.

So sit tight, read and re-read, ask questions if needed. Here goes,

In digital electronics there are only two states, 1 or 0, these ones and zeros can be represented as either on or off on a wire, card intact, or hole punched on a punch card, inline or sideways as the domain of the magnetic charge on an HDD platter, charge present or charge not present in an SSD hard drive, it's either something or not something, unlike analogue electronics where there is an infinite range, in binary there is only two states.

I'll use 4 bit binary (because it's going to be easier to write out).

Numbers in 4 bit binary are counted like this

0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = 8
1001 = 9
1010 = 10
1011 = 11
1100 = 12
1101 = 13
1110 = 14
1111 = 15

So with two symbols, and 4 places for those symbols to sit, you can represent 16 numbers, in this example I represented number 1 - 15, 16 would be 10000, and 17 10001 so on and so fourth.
255 = 1111 1111.

(from now on we'll call the places bits), so with a 4 bit number you can count to 15, with a 8 bit number you can count to 255.

You might not be able to see immediately, but the bits have a value assigned to them

8 4 2 1
1 1 1 1 = 8 + 4 + 2 +1 = 15
1010 = 8 + 2 = 10

The left most bit when writing this way is the most significant bit [msb], (assigned the biggest value) the right most bit the one that is assigned a value of only 1 is the least significant bit (lsb)

Well, that's all very good you say, I can count from zero to a number as big as the amount of places I have in my number, but what about representing minus one, we use minus numbers all the time. When looking at the weather, or counting, minus numbers crop up all the time in our daily lives.

To denote a number as a signed number, we need to use a part of that binary representation to denote that it's negative, this is the signed bit.
Sadly, it doesn't just work like a minus sign so that whatever is after the signed bit can be read as that number, but this is not a lesson in binary, if you want to learn how to read binary either wait for an upcoming lesson, or Google search twos compliment.

Anyway, the signed bit is the msb, and the numbers now look like this.
0000 = 0
0001 = 1
0010 = 2
0011 = 3
0100 = 4
0101 = 5
0110 = 6
0111 = 7
1000 = -8
1001 = -7
1010 = -6
1011 = -5
1100 = -4
1101 = -3
1110 = -2
1111 = -1

So now my 4 bit space, 4 bit address space that is, can't count up to 15, any more, my 16 states are no longer 0 - 15, they are now -8 to +7

Now, you may want to read and re-read until you properly understand that, perhaps even ask questions in the comments, or even go off and search for a better binary tutorial. you can write the numbers out on paper, practice working out what numbers are. it is possible to program without knowing what the binary states are, but it'll help you when you come to realise the pin outputs of chips later on.

In maths whole numbers are called integers.
1 is an integer, 1.5 is not.
3000 is an integer, 523 is an integer, 3.147 is not an integer. anything that is not a whole number
is not an integer.

In the example above we looked at signed and unsigned 4 bit integers.

Now if you managed to read that all through and understand it, you may have surprised yourself what you've just learned, in a short space of time!

There are no 4 bit integers in C, (signed or unsigned) so you will have to use slightly bigger numbers (which as I said earlier will take up slightly more memory.

In C the standard space for an integer is 32bit, this means that the number range for an unsigned int is 0 - +4,294967295
the number range for a signed int is -2147483648 - +2147483647.

So that was the signed, variable modifier.

Earlier I talked about the size of space in memory, There are times when it's not appropriate to store 32 bit numbers, if your memory space is 8 bits, for example, and you need to store a 32 bit number, you're taking up 4 times the memory space (as those 32 bits need four 8 bit spaces to be stored in). if you don't have that space, then you'll be in trouble pretty quick.
or what about if you're only recording values of 0 - 255, and you;re logging them, you only need a 8 bit number, if you use 32bit address spaces you'll be using up memory twice as fast, that means that you might end up having to buy more memory in the shape of eeproms. Or that if you're on a computer, your disk space will be used up four times as fast.

So what if you want to use memory really efficiently? Well then you start to use modifiers, such as short, or to get bigger numbers you can use long. Short makes the address space shorter, and Long (in most cases) makes the address space longer.

Below is a table of the amount of bits in a number, and the number range given by that variable type and modifier.
            Data type    Bits                Range
short int 16 -32,768 -> +32,767
unsigned short int 16 0 -> +65,535
unsigned int 32 0 -> +4,294,967,295
int 32 -2,147,483,648 -> +2,147,483,647
long int 32 -2,147,483,648 -> +2,147,483,647

But long ints can also be 64 bit
to 9,223,372,036,854,775,807
It really depends on the architect of the system , on 32 bit systems ints are 32 bit and long ints are 32 bits, long longs are 64 bits, but on 64 bit systems, long ints are 64 bits.
on old Dos systems (16 bit) ints were 16 bit and longs were 32 bits. Basically, check your
platform to find out for sure!

So that's ints (in all their different types) covered, but lets say that you want to represent non integer numbers now. I mean non integer numbers occur in life all the time, if you have a cake and want to share it you get 0.5 of a cake.

Number that have decimal are called floating point numbers, floating point numbers are always signed, and the standard floating point number is assigned a 32bit address space, if you need a greater address space, then you don't use long floats, you actually use a data type called double (64 bit), after that there is a long double (96 bit).

the final data type is char, chars are 8bit numbers, so count either 0 - 255 as unsigned chars, or -128 - 127 as signed chars, chars are used for displaying characters. (for example from an ASCII chart of characters,

ok, to wrap up.

To define a variable, use declare the datatype, and ten give the variable a name.
int x;

if you want to modify the variable, you put the modifier in front of this:
short int x;

and if you want, you can assign a value to the variable as it's defined.

short int x=10;

You can also define lots of variables at once.
int x, y, z;

So lets wrap this up with a simple piece of code.

Go back to your coding folder and create lesson 2:

The code
First, you can add whatever comments you like

/* lesson 2, valiables */

Then you want to include the header file that contains all the necessary code to use the output device (monitor)

#include <stdio.h>

Now you need to decide whether you're going to define a global variable, or not a global variable.
at this stage of programming this doesn't matter, however, when you start creating subroutines and functions you're going to notice the difference then.

In this example I'll create a local variables, all this really means is that they are created inside of main routine, and are accessible to only that routine

It's generally bad practice to make variables global.

Now you want to setup your main subroutine in the same way that you did in lesson 1.

int main()
and declare your variable
int x;

Now give your variable a value...

x = 50;

Now display your variable.

printf("the variable X is %d", x);

And finish the main routine with a }
That printf statement was interesting, the way in which is works is that you put a little place holder into the text that you're printing (%d for ints), then after you close the speech marks you write down that variable name.

for signed ints you use %d
for unsigned ints you use %u
for floats you use %f
for chars (signed or unsigned) use %c
for strings you use %s, I'll cover strings in more detail in another time...

There is clearly a lot more, a lot, lot more, but I'm going to wrap up this lesson now.

The complete code is
#include <stidio.h>
/*lesson 2*/

int main()
int x;
x = 50;
printf("variable x = %d", x);

No comments: