The first C programming tutorial gave a quick history of the C language. Then, it talked about how high-level instructions get converted to the 1s and 0s a microcontroller can understand. Finally, we went over some good programming practice.
In this C programming tutorial, we’re going to talk about one of the core concepts of C, or any programming language for that matter. We’re going to talk about variables.
If you have a decent amount of C programming experience you probably know something about variables. You should still read this because, as usual, it will be a good review.
If you’re new to C or programming in general, understanding variables is not an option. You need to read this and know this stuff.
Of course, it’s hard to know who knows what, so we’ll assume you’re just getting started with C programming.
On we march into C programming tutorial 2!
C Programming Tutorial 2: Variables
An Introduction to Variables
Those that have studied algebra will be familiar with equations such as 2x = 6 where x is an unknown variable one needs to solve for. For this equation, I’ll use the term unknown loosely, as many of us can solve it by inspection. However, algebraic equations aren’t always so simple.
In the equation above, x can take on different values if we change the right side of the equation. In other words, the value of x varies depending on what we set the right side equal to. Hence the term variable.
The concept of variables in programming is very similar. The Internet tells me that in programming, “a variable is a symbolic name given to an unknown quantity that permits the name to be used independent of the information it represents.”
That’s sort of abstract.
A better abstraction (for now) is to think of a variable in C as a container that holds something.
When you were in middle school or high school your algebra book might have been stashed in your locker when not in use (if you’re anything like me, your algebra book probably spent most of its time in your locker, barely seeing the light of day).
Regardless of age, lockers are something most of us are familiar with. So, imagine a bank of lockers. Each locker is a container that can hold something.
Now, let’s say I want to write a program that checks the temperature every so often and logs the highest temperature in a given day. For this, I’ll need two lockers. I’ll need to store the current temperature in one and I’ll need to store the highest temperature in the other.
When we first start, the two will be equal. For example, say I start logging temperatures at midnight because that’s technically the start of a new day. It’s 58 degrees Fahrenheit outside, so not only is that the current temperature, it’s also the maximum (so far) as we’ve only taken one sample.
But as the day progresses, both will update or change and eventually the temperature will reach a maximum before falling again.
So, at noon the temperature is 68. We take the number 68 and put it in both lockers. Then at 2 pm the temperature drops to 67. Now we’ll put 67 in the current temperature locker but keep 68 in the high temperature locker as 68 is the highest temperature (so far) today.
The current temperature will continue to vary throughout the day. The high temperature will vary until we reach the maximum for that day.
C Programming Tutorial 2, Lesson 1: think of variables as containers that hold something.
Variables and Data Types in C
If you’re new to C programming, your next question may be something like what else can I put in a variable?
We know that different containers are good for storing different things. We also know it’s very helpful to the have the RIGHT container for the thing we want to store.
Let’s use a typical grocery store as an example.
Eggs are stored in an egg carton which is appropriate because it protects them and makes them easy to access. You’ll often find milk in a plastic gallon jug. Sometimes, coffee is vacuum packed in little bricks.
We know it wouldn’t make much sense to put a gallon of milk in a plastic bag rather than a jug. Nor would it make sense to try to vacuum pack eggs. And we wouldn’t pack coffee in an egg carton.
So it is with variables in C — each type or variable is good for storing certain things.
This is referred to as the variable’s data type.
Going back to our temperature/locker example we may want to use an integer data type for this if we’re only interested in whole numbers (an integer is a whole number with no fractional part).
To do this, we need to declare two integer variables:
In general, when declaring a variable, the form is:
Data Type Variable Name = something;
Notice though that we didn’t set our two variables equal to something, as this wouldn’t make sense for our purpose. The temperature is what it is, and the variables will take on that value without us explicitly setting them equal to something.
Setting a variable equal to something is referred to as initializing the variable and it’s optional. Sometimes you know ahead of time what the initial value of your variable will be, sometimes you don’t.
In C, we initialize variables with a single equal sign (=), which is called the assignment operator. We’ll talk more about the assignment operator vs the equal sign (which in C is ==, not =) in another lesson.
C Programming Tutorial 2, Lesson 2: variables consist of a data type and a name. Initializing a variable is optional.
In our temperature example, our variables were put in lockers. In a computer or microcontroller, variables are put into memory, usually some sort of register or the stack. This is an introduction, so I won’t go into too much technical detail about registers and stacks at this point.
There is one more important point to note before we move on and talk about specific types of variables and what they’re good for.
There are certain words or “names” that are off limits. These are usually keywords that the IDE reserves for its own use.
For example, when programming in the Arduino IDE we can’t name a variable something like High or Low. These are keywords the IDE reserves.
When programming a naked micro in C, you wouldn’t be able to use the words void or return to name a variable. These are keywords in C.
If you do either of the above, your code won’t compile, and you’ll get an error.
C vs Arduino, Size Matters
Also, as we’ve talked about before, C and the Arduino programming language have some differences. Due to this, some Arduino data types won’t work in C and vice versa. I’ll cover the common ones for both platforms.
Finally, the maximum size of these data types depends on whether you’re using a 16-bit, 32-bit, or 64-bit processor. For example, an integer in a 16-bit system is 2 bytes (1 byte equals 8 bits). In a 32-bit system an integer can be as large as 4 bytes. Regardless, C guarantees that an integer will be at least 2 bytes, regardless of the platform.
Since the Arduino Uno uses a 16-bit microcontroller and most 16-bit naked microcontrollers are sufficient for most projects you’ll likely do, we’re going to assume a 16-bit system.
Just know that if you delve into 32-bit or 64-bit processors the number of bytes a certain data type can hold will probably be larger.
C Data Types: What Goes Where
The C programming language has been around for a while. Because of this, there are a lot of data types. I won’t cover the more esoteric ones here. We’ll stick with the most common ones you’re likely to use.
We’ve already touched on integers. Out of all the data types, you’ll probably use integers the most.
As you may know, an integer is a whole number which can be either positive or negative.
The value of an integer can range from -32,768 to +32,767. It takes of 2 bytes of data, regardless of the size of the number you use.
Declaring an integer is really simple:
int myInteger = 800;
However, one must be careful to make sure an integer always stays within the range it’s supposed to be, or weird things can happen. For example, if we add 1 to 32,767 we don’t get 32,768, instead it rolls over to -32,768. This is because 32,768 is too big to store as an integer.
Most data types will “roll over” once you exceed their maximum value. This will cause logical errors in your program that may be tough to find.
C Programming Tutorial 2, Lesson 3: when you create any kind of variable, you need to have some idea of what type of value it will hold and how big or small that value will get.
So, what do you do if you need to work with a number like 62,543?
That’s where the unsigned integer comes in. An unsigned integer can only be positive, but its range is 0 to 65,535. The example below shows how to declare an unsigned integer:
unsigned int big = 62,543;
Note that unsigned integers will also roll over (like most data types) to zero if your program inadvertently adds 1 to 65,535 — so be careful!
Long and Longer
Still need an even bigger number?
No problem, just use a long which has a range of -2,147,483,648 to +2,147,483,647. The example below illustrates how to declare a long:
long evenBigger = 348,962,512;
A long takes of 4 bytes of data, regardless of its size. Just like the other data types, a long will roll over if the value is exceeded on either end.
You can also have an unsigned long with a range of 0 to 4,294,967,295, like the example below:
unsigned long gigantic = 4,000,000,000;
If 4,294,967,295 isn’t big enough for you, just use a long long int. To declare it, type something like:
long long int = somethingReallyHuge;
Its range is −9,223,372,036,854,775,807 to 9,223,372,036,854,775,807. You can also use the signed or unsigned prefix with a long or long long.
C Programming Tutorial 2 Floats On
What if we need to store a number that is not a whole number, like Pi?
If I try to put a number like Pi into a variable with data type integer, I’m going to have problems. For example, the statement:
int Pi = 3.14;
would not work because 3.14 is not an integer.
That’s where a float is used. The float data type has a huge range from -3.4028235E+38 to +3.4028235E+38. To declare a float, follow the examples below:
float Pi = 3.14159265;
float anotherFloat = 3.14E3; //this is the same as saying 3.14*10^3 which is 3,140
A floating-point number corresponds to what mathematicians call a real number, which includes numbers between the integers.
Floating-point representation involves breaking up a number into a fractional part and an exponent part and storing the parts separately.
Floats occupy 4 bytes of space, however the bigger the float the less precise it is. Depending on what you’re doing this can be important.
What do we mean by precise?
Because there is an infinite number of real numbers in any range—for example, in the range between 1.0 and 2.0—computer floating-point numbers can’t represent all the values in the range. So, we can probably get away with storing and retrieving 1.1234 accurately, but if we try to store the number 1.234567890123456789 we may run into trouble where the computer drops some of the digits at the end or rounds the number to some nearest value like 1.2345679. More on precision in later tutorials.
C Programming Tutorial 2, Lesson 4: floats can huge, but their precision has a limit. Precision can be important.
I Like Mine Charred
Finally, we have the char. Char stands for character and takes 1 byte of storage. Normally, you’d use a char to hold a character such as a letter or symbol. They range from -128 to +127.
There are two ways to declare a char, shown below:
char letter = ‘z’;
char number = 98;
Notice in the first case, we put single quotes around the letter. When declaring a char as a letter (which is actually interpreted as an ASCII value) you need the single quotes.
When putting a number in a char they are not necessary. Note that when you declare a char as a number, what’s actually being stored is the letter or character whose ASCII value corresponds to that number. In the second declaration, 98 corresponds to a lower-case b in ASCII.
Chars can also use the signed or unsigned prefix.
The Arduino IDE uses the byte data type. It is not found in regular C.
Bytes take up 1 byte of space and have a range of 0 to 255. These can come in handy if you’re really pressed for program space and know your value won’t go out of this range. The example below shows how to declare a byte:
byte smallNumber = 16;
Wrapping Up C Programming Tutorial 2
All the above is a lot to remember so I’ve included the nifty chart in figure 1 which summarizes the data types we went over. Bookmark this page.
Figure 1: common C programming data types.
Until the next C programming tutorial, I encourage you to download the Arduino IDE (get it at Arduino.cc under the software, then downloads tab) if you haven’t already. Play with it and load some of the example programs (called “sketches” in the world of Arduino). In the next C programming tutorial we’ll download a regular C compiler so we can write our first program (outside of the Arduino IDE).
Comment and share your level of C programming experience. Are you a beginner? Expert? Let us know!
Want to get started with Arduino & microcontrollers? You’ll love the new course How to Get Started With Arduino in 1 Day or Less![thrive_leads id='2917']