# C Variables

To begin, C has several data type definitions.

They include:-

byte – eight bits – value 0 – 255
short – 16 bits – value 0 – 65535 – (not 65536 as I had previously written – you happy now, those that want to criticise?)
int - 32 bits – value 0- something big. – Integer only which means no fractions.
float – 32 bits – 0.0 to +/-some ungodly high number.
Double Float – 64 bits 0.0 to +/-some even huger high number:)

When I say +/- that means you can have + or minus numbers, like -0.12 or 0.45

Then you start getting into signed variable types. For instance

signed byte – integer, value -128 to +127
signed short – integer, value -32768 to 32767

and so on.

Basically the compiler treats the top bit of the data type as a sign indicator. If bit 8 in a byte is 1, then we are a minus number. So with a signed byte 11111111 = -1, an unsigned byte of 11111111 = 255. The two types are interchangeable; the reason for the difference is for the compiler to create correct if/then situations. For instance,

if ( x == -1)
{
blah;
}

would be very different if x is an unsigned byte than if it’s signed, since you can never get –1 on an unsigned byte. Get the difference?

By default all integer variable types are considered unsigned by the compiler.

There is one more type of variable, and that’s the CHAR type. It’s actually an unsigned byte, but it’s considered part of a string.

Strings are arrays of chars. For instance the string “Hello World.” is an array of chars that is 12 chars long. (Actually 13, since the last char in the array is always a zero value, which tells string routines that the string
has ended.)

Booleans

A Boolean is a predefined data type, like an int, that already has all the values you can assign to it pre-defined. In this case, you have two possible, and those are true and false. So you’d define and use a boolean variable thusly

boolean file_test;

code…

if (file_test == true)
{
blah;
}

In actual fact, a Boolean is pretty much just an int that is either a one or a zero.
C defines it a bit more rigidly than that, but that’s effectively what it is.

Other Data Types

There are some more data types, like those that you define yourself, but that’s beyond the scope of this initial look at data types. We’ll get to them later.

Using Variables

How do we use variables? How do we declare them? Here are some examples.

char text[10];
byte count;
int var1;

Some notes here. Firstly, C compilers all use LOWERCASE operators – the ‘byte’ is considered an operator. If you put them in upper case, the compiler won’t recognize them. Secondly, all variable names are case sensitive. You can create VAR, Var and var, and they are all different variables as far as the compiler is concerned. Thirdly, all of C uses semi colons as statement closers. A ‘;’ tells the compiler “this line is at an end, process it / run it, then move on to the next one”.

Now, when we define variables, we can actually assign a value to them at creation time.
If we don’t do this, then we have to ensure that the variable is initialized somewhere, or we will have random values in it when we try to use it. Depending on your compiler, it may or may not tell you this when it’s doing the compile.

Also, the compiler will stop you using variables that are keywords. For instance you cannot define a variable named if, or and etc.
This is a bit weird here, since some compilers will complain, and some let it go. Better just to be sure and never use them.

Some examples of initializing variables.

char text[20] = “Hello World.”; – note, the compiler will put the zero on the end of the string for you, you don’t have to worry about it.
int blah = 200;
float    stuff = 0.134f;
int    wally = 0×045;

Some more Notes :-

Notice that the float requires an f on the end of the value used. This is so the value that’s put in the float is set up as a 32 bit floating point value, not a double (64 bit) value. This is just something C does. It makes sense to use straight floats and not double floats most of the time, since usually the main processor works in 32 bits, not 64, and also since 32 bits of float has way enough precision for almost everything you need to do.

Notice also that the wally variable is defined in hex rather than decimal. Putting a 0×0 on the front of a data definition tells the compiler – this is a hex number, not a decimal one.

bytes and shorts are ok to use as normal data types, but really, you are better off using ints for almost everything. The processor works best when it’s retrieving data from memory on 32 bit boundaries. Since int’s are all 32, you are good to go. If you mix bytes and shorts, you can end up with data that’s not 32bit aligned, and that can slow down the processor a bit. Besides, who cares about memory usage these days? Note, you have no choice about strings being char types.

Lets take a second and talk about arrays. Incase you aren’t clued up on what arrays are, they are basically data structures that repeat the same data type in memory. For instance

byte array_1[10] = {10,9,8,7,6,5,4,3,2,1};

will set up 10 byte values in memory, one after the other. To look at each cell, you would use an index into the array. For example array_1[3] equals the value 7. IMPORTANT. – While you define arrays from 1, the actual index values will start from 0. So, if you set up an array with 10 values, like we did up there, you actually get values 0 to 9. array_1[0] = 10, array_1[9] = 1. Remember this. It’s confusing, but you’ll see why it’s this way later.

To access any cell or position in the array, you place the index of that position or cell in square brackets after the variable name, as you see from the example above.

#DEFINES

One last thing we can talk about right now is that C allows you to set up pre-defined variables. These is really helpful in setting up variables you use a lot in code in one place, so if you need to change them, you only have to go to one place. The structure of this is the #define stuff.

Quick aside, any instruction that has a # in front of it is a compiler instruction. This means it’s an instruction for the compiler, not for the finished object code. These are called Compiler Directives, since they only affect compilation of the code, not it’s actual running.

For instance the snippet

#define _OSX

#if _OSX

code we do if we are running on a mac

#else

code we do if we are running on Windows

#endif

would only compile the code for running on a MAC, not the PC stuff. If we changed the
#define to a #define _OSX 0, then we would get the PC code instead. This is done at compile time, not at run time.

Notice also that you don’t actually have to do a #if _OSX = 1. All of C makes this assumption.
If you do an if (blah), then you are saying if blah is not zero or null, then go forward. You’ll see this time and time again.

Anyway, the #define is great. You can set floats with it, strings, the lot. A common way to determine that a variable you are looking at is a #define is to use only upper case for it. That way I would know that INITIAL_VALUE in the following code snippet is set up somewhere as a #define. A good rule of thumb is that normal run time variables are almost always lowercase.

#define INITIAL_VALUE 20.0f

void main(void)
{
float    c;
int       d;
float    e;

c = 0;
d = 0;
e = INITIAL_VALUE;
}

Notes on #DEFINES

Notice a few things about this. Firstly when you do the #define, there is no semi colon on the end. That’s because a #define is quite literally viewed by the compiler as a ‘search and replace’ function would be in a word processor. The compiler starts up, hits the #define and says “ok, from now on every time I see the variable INITIAL_VALUE, I’m just going to replace it with the value assigned to INITIAL_VALUE, which in this case is 20.0f.

Be aware that you can’t stick a floating-point value into an integer. The compiler should complain if you try and do it.

Usually, you would put your #defines inside of .h files, so more than once .c file can see them.

One last thing. There are actually loads of different ways of doing initialization.
There are some short cuts you can take as well, and we’ll list a couple here.

float a, b, c, d;

creates all the variables at one go.

float a, b, c, d = 0.0f;

creates and sets all the variables at once to a value of 0.0f.

Once variables are declared, you can set a bunch of them to the same value in one line of code.

a = b = c = d = -1.34f;

sets a, b, c & d to -1.34 at the same time.

Enumeration

I know I said this would be the last topic, but I lied. I’m just going to go into Enumeration quickly, since this is so cool. Enumeration is a way of creating variables that equal an acension of numbers. Wow. That sounds really complicated, but it’s really not.

For example

enum
{
WEAPON_PISTOL,
WEAPON_SHOTGUN,
WEAPON_LAUNCHER,
WEAPON_PLASMA,
WEAPON_GRENADE
};

will set up a bunch of variables that are set up numerically in ascending order. WEAPON_PISTOL will equal 0, WEAPON_SHOTGUN will equal 1, WEAPON_LAUNCHER will equal 2 and so on. This is nice in your code since you can set these up once, and then assuming you use them all over you code instead of the real numbers (e.g.

if (blah == WEAPON_LAUNCHER)

instead of

if (blah == 2)

you can reset and move the order of the definitions as you please, and the code will still run the same.

There are a couple of other clever things you can do with enumeration – we won’t get into typedefing just yet, but we can talk about setting the initial enumeration value. If we had written

enum
{
WEAPON_PISTOL = 3,
WEAPON_SHOTGUN,
WEAPON_LAUNCHER,
WEAPON_PLASMA,
WEAPON_GRENADE
};

then WEAPON_PISTOL would equal 3, WEAPON_SHOTGUN would equal 4 and so on. It’s just a way of pushing up the initial value of the enumeration.

Right, that’s enough of basic info on data types. We aren’t going to get into static or constant data types just yet, and we certainly aren’t going to deal with unions here, but we’ll get there eventually.