Tutorial - Preprocessor, Printing, Variable types

Main Page
Helpful Links
Downloads
Tutorials
Grades
Syllabus
Contact Me
     By this point, you should be familiar with using Unix, and operating the GCC compiler.  Below, I go over some basic elements of the C language you can use for constructing simple programs.  I cover the preprocessor, variables and types, assignment, and printing output to the screen.  I defer collecting input for the next lesson since it proves to be mildly complicated in C.


The Preprocessor

    The preprocessor is a program that is run on text documents before the compiler actually compiles them.  What it does is looks for preprocessor directives, and acts upon them to edit the documents.  It is these edited versions the compiler actually sees.  You never actually see them (unless you really want to) because they are stored in some garbage directory where they'll be deleted later.
    There are two preprocessor directives we will make common use of, #include and #define.

#include

   This preprocessor directive is used to link in the text from a header file with the extension .h.  These contain declarations and things of that nature.  All it really does is cause the preprocessor to dump all the text from the specified file into your program at that point.
   Libraries within your standard search directories are specified using angle brackets <>  while other, non-standard libraries are specified with "".  I almost all programs, you put in the declaration #include<stdio.h>.  This tells the preprocessor to put in the declarations for input and output in stdio.h into the file.

#define

    This is used to define an alias for something.  Let's say you need the value of pi for some purpose, multiple times in your program.  You could put in a line like this:

#define PI 3.14

    This makes it so that every time PI appears in your code, it will be replaced with 3.14.  The purpose of using #defines is making it so that if you have to change something, you only need to change it in one place.  Suppose you needed more a more precise version of pi.  You might have used it many times in your program.  But this way, you could simply change it at the #define statement:

#define PI 3.14159265358979323846

    Remember two things.  One, #defined constants are not variables.  Any attempts to assign values to them will result in errors.  Two, it's good style to name them in ALL CAPITAL LETTERS.  This simply makes it clear what they are.


Comments

    Comments are text the preprocessor simply removes before compilation.  So, what do they matter then?  They matter because they allow you to put notes into your programs.  These make it easier to understand your program, especially when other people will be reading your code.  Make ample use of comments.
    There are two kinds, single-line and multi-line.

//    The double slashes are a single-line comment.  Everything after them is a comments.

/*    This is a multi-line comment.

       Until the closing part is supplied.  Everything is a comment.  */


The Main Function

int main(){

// code goes in here
return 0;
}

    This is an empty example of the main function.  It is where a program's execution begins.  There can only ever be one main function in a program.  There are some variations to it though.  Here are several valid main functions.

int main(void){

// code goes in here
return 0;
}

    The above main is actually 100% identical to the first.  By placing void into the parentheses, we simply explicitly say we're not accepting any arguements from the operating system.


void main(){
// code goes in here
}

    This main function is declared to be type void instead of int.  Also, notice there's no return statement.  This means we're not returning any value to the operating system.  This form isn't typically a good idea, and the compiler will usually give warnings about it.

int main(int argc, char** argv){
// code goes in here
return 0;
}

    This form allows the main function to collect arguments from the operating system.  We won't be covering it for a long time, but this is basically how a program like GCC processes the things typed onto the line after it.


Variables

    Variables are portions of memory a program manipulates.  They are like containers for information.  In C, there are several types, which come in different sizes for holding different types of data.

Types

Type
Details
int
    This is the type for holding integers, whole numbers.  It can hold negative as well as positive numbers.  It has a finite range.  On a system with 16-bit integers, it can hold numbers from -32,767 to 32,767.  In other words, there are 216 possible values.
unsigned int
    This holds integers with no negative values.  For a system with 16-bit integers, it can hold values from 0 to 65,535.  Again, 216 possible values.
float, double
    These types are used to store real numbers, which may have decimal portions.  Unlike the int type, there is always a degree of imprecision with these, since there are many numbers, such as 1/3, that can't be perfectly represented.  This makes them unsuitable for comparison using the equality operator (==).
    The double type is typically twice the size of the float type, giving it greater precision.
char
    This type is used to store character data.  It stores values like 'A', 'b', or '?'.  It is 1 byte (8 bits), so it can store 256 values.  In truth, it's a lot like int.  It holds values from 0 to 255.  These values are then interpretted as characters using the ASCII encoding.

    Keep the ranges of the integer variables in mind, especially when doing arithmetic.   If you add something to a variable and go up over its limit, the value will wrap back down to zero.  While these values are for a 2-byte system, I believe CSE runs on a more modern 32-bit (4-byte) system.  I leave it to you as an exercise to find out the limits on there.
    There are other types, including custom ones you yourself define, and pointers, which are variables pointing to other variables.  We'll get into those much later, but keep them in mind.


Variable Declaration

    Declaring variables is easy.  You simply type the type you want, followed by the name you want to give your variable.  Always choose a descriptive name for your variables.  This, along with comments, goes a long way towards keeping a program easy to read.

    For example, this declares an integer, a float, and an unsigned int:

int xCoordinate;
float ratio;
unsigned int guests;

    Remember though, that until you assign something to the variable, there may simply be gibberish in the variables.  It's just leftovers in the memory from other things.

Variable Assignment

    We can use the assignment operator (=) to assign values to a variable.  The (=) operator always has a variable on it's left, and something with a value to the right.  This is so it can take the value from the right side, and assign it to the variable on its left.
    For example:

unsigned int age;
char middleInitial;

age = 21;
middleInitial = 'S';

    One nice thing is that we can assign to variables as we declare them.  This is known as initialization.  So, here's an example:

int xCoordinate = 12;
float ratio = 0.5f;
unsigned int guests = 3;

   
One thing to remember is not to confuse the assignment operator (=) with the equality operator (==).  We won't be covering (==) for awhile, but just remember it's there.

Printing Output

    A program has to be able to generate output.  To do this, we make use of the printf function, defined in stdio.h.  It's called printf because it prints out formatted output.
    Basically, the way it works is you give it a format string, and a list of variables.  The format string contains format specifiers.  For each of these, it will take the corresponding variable, convert it into characters, and insert it into the string.  When complete, it prints the finished string to the screen.
    Here's a list of a few common format specifiers we will use:

Specifier
Description
d,i
Specifies an int.
u
Specifies an unsigned int.
c
Specifies a char.
f
Specifies a float or double.

    As an example of it's use, consider us wanting to print out how many apples we have:

unsigned int apples = 12;

printf("We have %u apples.", apples);

    We declare an unsigned integer called apples.  We then call printf.  The first argument is a format string, which specifies a format using % followed by one of the format specifiers.  In this case, we specify an unsigned integer.  We then give it the variable apples as its second argument.
    It decides how apples should be turned into characters, and then inserts it into the string, replacing the format specifier.
    There is much more to printf than this.  It can also be used to dictate how many digits of a number should be shown, how to align it, and things like that. 
    Always make sure you give exactly as many variables as format specifiers, and that their types match.  If you feed the wrong variable to a type specifier, bad things can happen.