Starting Out Top Testing code examplesThe C Framework Contents

The C Framework

Working with C requires that you be able to edit a text file. I use vim as my text editor. Vim is an editor that was written by programmers for programmers (emacs is another such editor) and Serious Computer Scientists and Programmers should learn either vim or emacs.

C also requires that your program follow certain guidelines, such as your source code having a function called main. You may not know what a function is, so we are going to give you an entire program for you to enter into a file named hello.c. By convention, all C programs and modules (we will learn about modules later) should be stored as text files with the filenames ending in .c. Please note that case is important - you must enter a lowercase .c.

Your first program

Using vim (or emacs), place the following code in a file named hello.c:

    int
    main()
        {
        printf("hello, world!");
        return 0;
        }

Save your work and exit the text editor.

Now issue the following command at the system prompt to compile the file:

    gcc hello.c

Compiling and linking (more on linking when we get to modules) is the process of turning source code (what you placed in the file hello.c) into executable code (code that your computer can understand and run). If you do a directory listing after running the above command, you should see a new file created named a.out. This new file contains the executable code. To run the code, one types the command:

    ./a.out

You should see the phrase:

    hello, world!

displayed on your console. Note that if you are using Cygwin, the executable will be named a.exe, instead of a.out. Here's a trace of both commands:

    lusth@warka:~$ gcc hello.c
    lusth@warka:~$ ./a.out
    hello, world!
    lusth@warka:~$

where lusth@warka:~$ is my system prompt; yours will be different.

More advanced compilation

Most advanced programmers do not compile this simple way. The command you should use from now on should look something like this:

    gcc -Wall -g hello.c -o hello -lm

The term -Wall tells the compiler to issue all warnings. This will tell you if you have some stylistic or other non-critical errors in your code. In the Linux world, terms beginning with a dash are denoted options. The -g option tells the compiler to save information in the executable code that will allow you to debug the code should you need to. The -o option says to forgo a.out as the name of the executable file; rather the name following the -o should be used instead. In the example above, the name of the executable file is designated to be hello (no extension). By convention, the name of the executable file is the base name of the .c file that contains the main function. Finally, the -lm at the end of the gcc command adds in some important math functions.

If you ran the gcc command with the -Wall option, you would see a couple of warning messages generated:

    lusth@warka:~$ gcc -Wall -g hello.c -o hello
    hello.c: In function 'main':
    hello.c:4:5: warning: implicit declaration of function 'printf'
    hello.c:4:5: warning: incompatible implicit declaration of built-in function 'printf'

You will receive many such warnings in your C programming career. The warning states that we are calling a built-in function named printf, yet we haven't told the compiler how one calls the printf function1. We fix this problem by telling the compiler to look for the missing information in what is known as a standard header file. Header files, by conventions, end in .h. We use the include directive to indicate the name of the header file. Our program now becomes:

    #include <stdio.h>
    
    int
    main()
        {
        printf("hello, world!");
        return 0;
        }

With this addition, our program compiles without any warnings issued.

From now on, always use the -Wall, -g, and -o options when compiling unless you have good reason not to.

Breaking down hello.c

Let's look in more detail at the hello.c program. We have annotated it to show the line numbers:

    1:    #include <stdio.h>
    2:    
    3:    int
    4:    main()
    5:        {
    6:        printf("hello, world!");
    7:        return 0;
    8:        }

As stated previously, line 1 is an include directive, which informs the compiler what a call to the printf function (among many functions) should look like. We can tell we are including a standard header file by the use of the angle brackets (the less than and greater than symbols). A standard header file is installed for you automatically and you generally don't need to know where it is located2. Later, we will learn how to define and include local header files.

Line 3 holds the return type of the main function. You can think of a function as a little factory. It takes in raw data and produces refined data or information. The data, whether raw or refined, is made up of the primitive values or collections thereof. These values all have types, which you will learn about in the next chapter. One of the primitive types is int, which stands for an integer. So line 3 is saying that the main function will produce an integer as a result of the work it does.

Line 4 holds the name of the function (in this case main) and a comma-separated, parenthesized list of the receptacles that will hold the incoming raw data (in this case, there are no receptacles). If main had required some incoming raw data to do its job, the names of the receptacles and the types of data the receptacles hold would be listed between the parentheses. As hello.c is such a simple program, the main function does not need any incoming data, leading to the empty set of parentheses. Together, lines 3 and 4 compose the signature of a function. Later on, you will learn more on functions, function signatures, and formal parameters (the official name of the receptacles that hold the incoming raw data).

Line 5 is an open brace, which indicates the beginning of a block. A block is a section of code which is run sequentially. A line of code that appears earlier in the block is executed3 after any preceding code in the block and prior to any subsequent code in the block. Line 8 holds a close brace, which indicates the end of a block of code.

Lines 6 and 7 are the lines of code in the block that is associated with the main function. We visually show the block belongs to main by indenting it. Line 6 prints out the message we see when we run the program. Line 7 gives the refined data value that the main function produces as a result of all its work. In this case, it says that the main function returns a zero when it is done. Note that zero is an integer, which matches the return type found on line 3. The return value of a function is almost always used in some way, often serving as the raw data to be given to some other function. In the case of main functions in C programs, the return value of main indicates whether or not the program ran successfully. By conventions, a zero return value from main means 'zero errors'. If an error occurred, some other integer value would be returned. We will learn how to choose between returning zero or some other integer when we learn about conditionals.

All C programs require a main function, so until you can write a main function for scratch, use the following version as a starting point:

    //template for testing code
    //download with: wget troll.cs.ua.edu/ACP-C/tester.c
    #include <stdio.h>     // Provides standard I/O functions
    #include <stdlib.h>    // Includes a number of basic built-in functions
    #include <string.h>    // Provides functions that operate on strings
    #include <math.h>      // Provides a wealth of mathematical functions

    int
    main(int argc,char **argv)
        {
        /* place code here */

        return 0;
        }

You'll notice this version has a few more include directives plus a couple of formal parameters for the main function. These formal parameters accept any command-line arguments (as stated earlier, command-line arguments will be covered in a later chapter). In addition, the very first line is a comment, meaning it is there to be read, but is otherwise ignored by the C compiler. Comments that begin with // are called line comments; the compiler ignores those characters and every character beyond on the same line. The template program exhibits another style of comment, the block comment. In a block comment, the /* and */ characters and all the characters between, are ignored by the compiler. The advantage of block comments is that they can be placed in between source code bits and can also span lines.

About C programs and whitespace

Other than line comments and include directives, there are no rules for C programs specifying what parts of the programs have to be on what lines. For example, the template program above could have been written like this:

    //template for testing code
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    int main(int argc,char **argv) { /* place code here */ return 0; }

Note that the entire main function is on a single line. This is because C is a free-format language. A free-format language says wherever you can have whitespace (a space or a tab or a newline), you can replace it with some other kind of whitespace or any combination of whitespace characters.

Vim and C

In order to be most efficient at programming, one needs to configure the editor to understand the language being edited. We will do that now.

Move into your home directory with the:

    cd

command and list the files found there with this version of the ls command:

    ls -al

If you see the file .exrc, then all is well and good. If you do not, then run the following command to retrieve it:

    (cd ; wget troll.cs.ua.edu/ACP-C/.exrc)

This places a copy of the .exrc file in your home directory. It contains a number of commands that help customize vim for writing C programs, they configure vim to understand C syntax and to color various primitives and keywords in a pleasing manner. These commands are processed every time that you invoke vim.

Four Shortcuts to Improve Efficiency

You can program your entire life without knowing the following four shortcuts. However, that is the same as typing http:// on every website that you visit. You can save time if you know a few basic tricks for the edit-compile-test cycle.

Running a Program without leaving the Editor

Since you spend a lot of your development time in the edit-compile-test cycle, being able to compile and test your program without officially leaving the editor can save significant time. We can add some macros (shortcuts) to vim so that compilation and testing of your program can be done while editing.

First, go to your home directory (cd) and check to see if you have an .exrc file. If you retrieved the .exrc file from troll.cs.ua.edu as described in Section 2.5, then this line already exists. If you do not have a .exrc file in your home directory then either copy it (as described in Section 2.5) or create the file yourself and add this line at the top of the file:

    map @    :!clear; rm -f a.out; gcc -Wall -g % -lm; ./a.out^M

The ^M part of the macro is not a two character sequence (^ followed by M), but a single character made by typing <Ctrl>-v followed by <Ctrl>-m. It's just when you type <Ctrl>-v <Ctrl>-m, it will display as ^M.

What this line says is that, when the @ key is pressed, the system should:

  1. clear the screen,
  2. remove the old a.out file,
  3. run the gcc compiler on the file you are currently editing and place the executable code in the default file named a.out,
  4. then run the executable code.

Remember, to save your work (:w is one method) before running this command. Also, if you are using Cygwin, then replace the occurrences of a.out with a.exe.

How does this work? Suppose you are editing a file named project1.c, then the @ command would be equivalent to you first saving your file, exiting the editor, and then running the commands:

    lusth@warka:~$ rm a.out
    lusth@warka:~$ gcc -Wall -g project1.c -lm
    lusth@warka:~$ ./a.out

You can see that the @ macro saves you quite a bit of typing!

Running a Program with Command Line Arguments from within the Editor

As you expand your programming knowledge, you will be writing programs that take command-line arguments when you execute them. These are simply data values that are provided when you execute the program. In these cases, you need to be able to enter them before hitting return on the line that invokes your program. So that ^M in the @ command above needs to be removed, as ^M represents an enter on the command line. Thus, we create a new macro # that is the same as the old, except the ^M has been removed. The # macro pauses to let you enter command-line arguments to your C program4.

    map # :!clear; rm a.out; gcc -Wall -g % -lm; ./a.out

As you did with the @ macro, add the line above to the .exrc file in your home directory if it does not already exist.

Configuring VIM to Display C Programs Elegantly

The commands below help vim to display C programs in a pleasing format. Make sure to add these lines to your .exrc if you had to create one from scratch:

    set autoindent
    set shiftwidth=4
    set tabstop=4
    set expandtab
    set softtabstop=4
    set smarttab
    syntax enable 
    autocmd FileType make setlocal noexpandtab

Cut and Paste in VIM using the Mouse

You can copy and paste test code with the mouse. On a Linux system, the copy command is Shift-Control-c, rather than Control-c used in Windows. This is because Control-c in Linux means "kill the currently running program". You will find Control-c quite useful when you write programs that don't behave like you think they should. The paste command is Control-v, just like it is in Windows.

Because you likely have autoindent turned on in Vim, when you get ready to paste, turn off autoindent with the vim command:

    :set noai

Then go into insert mode and do the paste. To turn autoindent back on, enter this vim command:

    :set ai

The .exrc file on troll has a macro that takes care of the pasting issue:

    map <F9> :set paste!

This macro toggles autoindent, so to paste with the mouse, press <F9> first. Press <F9> again to turn autoindent back on.

One Final Comment

In subsequent chapters, code that we wish for you to insert into the template C program, tester.c, given above will start with:

    //test

This is simply a shorthand notation used in the text. Mentally, you should replace //test with:

    //template for testing code
    //download with: wget troll.cs.ua.edu/ACP-C/tester.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <math.h>

    int
    main(int argc,char **argv)
        {

and follow the test code with:

        return 0;
        }

Computer Scientists are all about efficiency; we can make the process of testing code fragments in this book even easier. We do so by writing a program (no surprise there) that does this mental replacement for you; the program is called quickc and is discussed in the next chapter.

lusth@cs.ua.edu


Starting Out Top Testing code examplesThe C Framework Contents