Basic Data Types





Without ways to store data and manipulate it, a programming language would be pretty useless. Luckily, C can do just about anything you want to with data. Let's first look at the basic types of data, and then at the basic operations you can perform on them.

Whole Numbers

Integers are one of the simplest kinds of data to deal with, so they'll make a good starting place. Integers are things like -2 or 17 -- real numbers without decimal points. In C, as in most languages, you can create variables to hold different types of data. In C, all variables have an associated type. Variables also must be declared at the top of every function, and must be declared before they can be used. To declare an integer, we use int. An example of this is below:

main()
{
   int i;
   int j;
   /* More stuff ... */
}

This snippet of code declares two integer variables, i and j. These declarations can also be combined onto one line using a comma, like so:

main()
{
   int i, j;
   /* More stuff ... */
}

This is usually the way you'll see variables declared. It is important to note, though, that a variable declaration in C is not the same as a variable initialization. The two integer variables i and j don't have anything stored in them yet. You have to set them equal to something before you use them. We'll get to that in a minute, after we see the other basic types.

There are a few other types of integer variables worth noting in C. The first of these is the type short. short is just like int except that it takes up less memory. Memory is not as big of a concern these days as it was before computers were manufactured with huge amounts of memory. Similar to short is long, which takes up more memory that int. The advantage to using more memory is that you can then store larger numbers in the variable. The exact amount of memory that each of these types takes up is different from system to system. You can find out how much space each kind of variable takes up on your machine by using the sizeof operator. For instance, sizeof(int) returns the number of bytes taken up by a variable of type int (more about bits and bytes later).

Floating Point Numbers

The other major type of numeric data is floating point data. Floating point data is any number that contains a decimal point, like 3.14159 or 2.718281828459, or even 17.0. C treats all of these in the same way. The basic type for floating point data is float. There is also the type double, for "double precision floating point numbers." double uses more memory and can store bigger numbers. In this tutorial, I will tend to use double over float, but that's just me; you can use whichever you'd like.

Characters

Characters are the major type of non-numeric data in C (sort of). A character is any value from the ASCII code. Because of this, in some circumstances, characters act like integers, but we'll get to that later. Character literals are denoted in C by enclosing them in single quotes, as in 'a' or '\n' (this is the newline character that we've already seen. Even though it looks like two characters to us, C treats escape sequences as one. The is also true for octal representations of characters.). A character variable is declared as type char, and is defined to take up one byte of space.

Boolean Data

Boolean data comes in two types: true and false. Unlike many languages, standard C does not have a boolean type. Instead, the number 0 evaluates to false, and everything else evaluates to true. It is customary to use 1 for true and 0 for false, but not necessary. If you find this too confusing, you can add the following lines of code to the top of your program (usually before main()):

typedef int bool;
#define true 1
#define false 0

This piece of code lets you declare variables of type bool, and makes true synonimous with 1 and false synonimous with 0. It is worth taking a moment now to explain a bit about this code, because it can be very useful. The second two lines use another preprocessor directive, this time #define. During compilation, the preprocessor looks at the #define lines and replaces the first argument with the second everywhere it appears in your program. #define lets you declare constants usable throughout your program without using up extra memory, and also avoids some of the pitfalls associated with global variables. These are lines, though, that you DON'T want to end with a semicolon, since the preprocessor replaces terms with everything up to the end of the line. Had you instead written #define true 1;, true would be synonimous with 1;, which would cause all sorts of problems. I will go into more detail about the typedef mechanism later; for now, just trust me that in this case it makes bool synonimous with int.

Operations

So now that we've got all these variables, what do we do with them? That's where operators come in. Operators let us manipulate the data we've stored.

First of all, there are the standard mathematical operators: +, -, *, and /. These work more or less the same way they did in algebra class, and follow the same order of operations (multiplication and division are evaluated before addition and subtraction). Another necessary operator, =, doesn't work in quite the same way. = is the assignment operator; it lets you assign a value to a variable. Look at the following example:

main()
{
   int i, j;
   double d;

   i = 7;
   j = 9;
   d = 1.3;
   /* More code ... */
}

Now, we have initialized these variables so that they no longer contain garbage. We can now use them:

   i = i + j;  /* i now equals 16 */
   d = d + j;  /* d now equals 10.3 */
   i = d * j;  /* i now equals 92 */

Notice that in the last example, i gets the value 92 instead of 92.7. This is because we tried to assign a floating point number to an integer variable. When that happens, C truncates (it does NOT round) the number back to an integer. In this case, C changed the type of variable automatically. But you can also tell the program to change the type via a mechanism called "casting." Casting changes the type of a variable for one statement, though it does not change it permanently. A cast looks like the following:

   i = ((int) d) * j; /* In this case, i = 90 */

As you can see, a cast consists of putting a type name in parentheses before the variable you want to change. In this case, the cast truncates d before the multiplication, which sets i to 90.

C also has a modulus, or remainder, operator, %. For instance, 10 % 9 is 1, while 9 % 9 and 9 % 3 are both 0.

Many assignments are so common in C that there are shorthand forms of them. Recall the statement i = i + j; from the above example. This can be rewritten as i += j;. The two statements are synonimous. The kind of shorthand can be combined with most of C's operators. A list of the operators that can do this is below (don't worry yet about the operators you haven't seen):

+=
-=
*=
/=
%=
<<=
>>=
&=
|=
^=

C provides yet another shorthand in the increment and decrement operators. Instead of saying i = i + 1;, you can use i++;. The -- operator works the same way. Either of these operators can be used as either a prefix or a suffix, though it does change the meaning slightly. Look at the following example:

   int i, j;

   i = 1;
   j = 0;

   j = i++; /* Now, j equals 1 and i equals 2 */
   j = ++i; /* Now, j equals 4 and i equals 3 */

When you use the increment or decrement operator as a suffix, the assignment happens first; as a prefix, the assignment happens second.

The last class of operators I'll discuss here are the logical operators. Logical operators produce boolean values as their output. The operators are == for equals (WARNING! Notice that logical-equals is a double equal sign; a single equal sign is the assignment operator!!); && is the logical-and operator; || is logical-or; ! is logical-not; and != is logical-not equal. The use of these operators will become more clear in later sections.


Back to the Structure of a C Program   On to Basic Input/Output
Back to the Outline