Whenever a computer program is running, that program is storing and manipulating data! Some examples:
- The player’s health in Minecraft
- Which attacks a Pokémon has learned
- How many bombs are in Link’s inventory
Also recall that we have a computer component called RAM, which we called the “working memory” of the computer. Whenever a program starts running, the operating system carves out some space in RAM for our program to use. Then all of the data associated with that program (the numbers, text, images, and other data it uses) are stored in that section of RAM. We have our own little section of memory to play with now!
OK, so now that we have some memory, what about the “numbers/text/images get stored in memory” part? How do we fill our programs with DATA AND STUFF? In our program’s code, we can create things called variables to claim this memory and store things in it.
Variables are memory locations in our code that store values. Each variable has a name (that we use to access it) and a type. A variable’s type tells us what kind of data a variable can hold, and how to interpret that data.
You can think of variables like boxes that hold specific things.
int MarsAge = 6;Above is an integer variable, called MarsAge, and its value is set to 6. That’s how old my dog Mars is!
The name of a variable will never change, but the value of a variable usually changes a lot!
When we declare a variable, we have to include the type, the name, and (usually) the value:
// type name value
int playerHealth = 100;
There are some naming rules about variables (you can’t name a variable something weird like “M@rs”) but that’s not super important to for us to memorize right now.
Once a variable is created, we use the assignment operator (the equal sign) to store a value in the variable.
The equals sign is called the ASSIGNMENT operator, because we are ASSIGNING a VALUE to a VARIABLE. (said another way: we’re storing a value in a particular spot in our program’s memory)
What can we store in variables?
Ultimately, a variable contains a single value of a single type. But when we are assigning a value, we can do so in a number of different ways:
int x = 40; //Value of x is 40
x = 50; //Value of x is 50
x = x + 10; //Value of x is 60
int y = 40; //Value of y is 40
int z = x + y; //Value of z is 100 (60 + 40)
WRONG ways to use variables
In a new/blank project, inside your main function, write the following lines of code, and compile your code. What happens? Do you get a successful build?
int x = 50;
x + 10;
y = 30;
x + y = 50;
100 + 20;What went wrong with the code we wrote above? If you tried to compile this code, you would see compile errors, and get some idea for what didn’t work, and why. Whenever we work with values, they need to be assigned to variables; we shouldn’t just have a value randomly hanging out in our code! Remember, our code needs to be translated into instructions and data that a CPU can use to DO things. With the last line of code above, we’re basically shouting “120!” at our CPU, but that isn’t an instruction to do anything.
We are also encountering a problem when we try to put two variables on the left-hand side of the assignment operator. That doesn’t work! You can only assign a value to a single variable at one time (meaning a single location in memory), so trying to add two variables together and then assign ‘50’ to that… doesn’t make sense.
Types
So far we have only looked at variables with the int type (integer numbers). But what if we want to store and manipulate other kinds of data in our program?
float myFloat = 2.75f;
char myCharacter = 'd';
There are other data types we can use to represent specific kinds of values.
Floats can represent numbers with decimals (integers only represent whole numbers)
float temperature = 0.6543f;
float rotation = -47.8003f;The boolean type represents only two different values: TRUE or FALSE. A bool can only ever be these two values.
Wait, I can't make bools? Why?
You may get compile errors if you try to use booleans by themselves in C without an extra step… we’ll get to that soon!
bool myFault = true;
int gymBadges = 7;
bool hasAllPokemonBadges = (gymBadges >= 8);
int powerLevel = 9001;
bool isOver9000 = (powerLevel > 9000);Whenever we create a new variable, we MUST give it a type. And the type of that variable will NOT change! It stays the same, forever!
The name of the variable will ALSO stay the same, forever!
The value of a variable can (and will!) be changed without limit!
int x = 8000;
x = x + 500;
x = x + 501;
//It's over 9000!Each type is a particular SIZE
Integer variables store positive/negative integer values (whole numbers).
But… how BIG is an integer? How large can its value be?
Turns out, Integers are usually 32 bits in size (4 bytes). Because of the way integers are represented in binary, they have a min/max size: -2,147,483,648 to 2,147,483,647. (That’s -2^3$$^1 and 2^3$$^1)
But… WHY? Why are integers this size, and why do they have min/max values? Aren’t numbers… well, infinite?
Consider this thought experiment: suppose you want to run a program that loads all the digits of pi into memory, at once. How would you accomplish this?
Well pretend that we could store each digit of pi in exactly 1 byte (8 bits) of storage space (this is absolutely NOT how this works in real life, but this is a hypothetical, so go with it). So we start storing off pi:
1st byte = 3
2nd byte = 1
3rd byte = 4
4th byte = 1
5th byte = 5
6th byte = 9
7th byte = 2 …
So, where are we storing these digits, physically, on our PC? Recall that our PC uses RAM for its working memory. So as our program runs, we will be filling up each byte of RAM with digits of pi. But pi is infinite, so we will eventually run out of space!
The whole point of this thought experiment is to bring home the point that numbers on PCs are not infinite. We use particular data types to represent particular ranges of numbers for particular programming purposes.
Integers are positive/negative whole numbers. Usually they are 32 bits in size, and their range is from -2,147,483,648 to 2,147,483,647.
When a CPU operates on data, it uses registers to do so. Registers are basically little storage spaces on the CPU where instructions and data are loaded. Because these registers are a particular size (usually 32 or 64 bits in size) it makes sense that data in our programs will usually align to multiples of this size as well:
//If we want to perform an operation between two pieces of data, the values
//of that data don't matter... as long as the representation of those pieces of data
//are the same size (number of bits) in binary, the CPU can operate on that data!
00100101001011110100000110111111 //This is 32 bits!
10100011011111000001110100100101 //This is also 32 bits!You can almost think of the CPU as a little factory/processing plant; everything flows smoothly when data is of a predetermined standard size, and can fit in exactly the right place in the CPU’s architecture.
Types Wrapup
A variable’s type determines two things: The SIZE of the data we are storing in that variable The way we INTERPRET that data
Keep in mind that even though an integer variable and a float variable are the same size (usually 32 bits), the binary representation of each type is VERY different, even if we interpret the numerical values as the same thing:
| Number and Type | Binary |
|---|---|
| 3, integer | 00000000000000000000000000000011 |
| 3.0f, float | 01000000010000000000000000000000 |
Said another way: An integer only holds WHOLE numbers, so we arange our binary representation a certain way to represent those numbers. A float holds decimal numbers, so we arange our binary representation a certain way to represent THOSE numbers.