C programming

Why learn to program in C?

  1. Practicality.

    Many, many companies/research projects do all their programming in C.

    Many, many existing programs are written in C, and you might be the one chosen to modify a C program.

    Further courses in the CS dept. (here at UW) may expect you to know C, or be able to pick it up on your own (which you may not have time to do!).

  2. It is an industry standard.
  3. It looks good on your resume.
  4. Concepts.

    C is occasionally called a "low-level," high level langauge. The semantics of C often mimic what actually occurs in the machine code. (or assembly language, if you prefer to think of it in that way).

    Due to the low level nature of C, the programming constructs that it provides to the programmer (such as pointers) are essential to know. Understanding these concepts and constructs may allow you to be a better programmer; one who can write better code, and code that runs faster. Please note that this is true, even if you only write Java code for the rest of your life!

354's assumptions about your background

  1. You have written high level language programs.

    Karen does not really care what language you know, but she will assume that you know Java. Why? Because it is the language that has been taught in CS302 (Introductory Programming) here for several years.

    Most examples in these lecture notes are given in C or Java. If you need some other language, let Karen know outside of class. She will attempt to modify lectures enough to help.

  2. You understand some basic program constructs, such as

Why did we learn Java in 302, if C is so common?

Object oriented (OO) programming (two examples: Java, C++) allow typing and structure that far surpasses non-OO languages. This has the further implication that a compiler can check for correctness of many more items within the source code. Therefore, more bugs are caught at compile time. The more bugs caught, the better.

Did you know that most completed, production code has lots of bugs? They just have not yet been tested for, or caught.

the Basics of the C Programming Language

C is a programming language that was invented (derived from B, actually) to be a low-level language that would facilitate more easily describing/writing operating system code.

It is general purpose.

The code itself is rather compact.

C is a procedural language. This distinguishes it from (later invented) object-oriented languages.

NO OBJECTS. NO METHODS ON OBJECTS.

So, your first question ought to be: how does anything get accomplished without objects and methods?

Karen's answer: Computers are really just fancy calculators. Combined with the stored program concept, computers are fancy (and fast) calculators that can re-do their calculations over and over.

What does a computer/calculator do? Arithmetic. On variables. Variables are numerical values that may change over time.

The C language manipulates variables. (Just like any other programming language.)

In a procedural language, procedures (also called functions or subroutines) are the equivalent of an object-oriented language's methods. In C, we call them functions. They operate on parameters (which are often variables).

The control structures (of Java) that you already know were derived from C! The designers of Java (C++, too!) knew that the vast majority of programmers already knew C. Since no one was complaining about the syntax used in C, and so many already knew the syntax, the designers of the Java language used the same syntax! This implies that learning C should be quite easy. . .

A Simple, Example C Program


#include <stdio.h>

#define MAX 100

main()
{
    int x;

    x = 1;
    while (x <= MAX) {
        printf("%d\n", x);
	x++;
    }
}

Here is the same program done a little bit differently:


#include <stdio.h>

main()
{
    int x;

    for (x = 1; x <= 100; x++) {
        printf("%d\n", x);
    }
}

Some things you need to know about C:
(you probably can figure out most of it without an explanation!)

Some other things you will want to know about C:

C Program: Source to Execution

The standard way to generate and eventually execute a program is much the same for all high level languages. In a diagram it appears as

 high-level
 language   -->  compiler --> assembly --> assembler --> machine
 source         (a program)    language   (a program)     code
 code

Once we have machine code,

 machine  -->  linking and loading --> program
 code          (program)               execution
                                       (program)
Without going into too much detail, Java programs do not ordinarily go through this set of steps. Instead Java programs are "executed" by an interpreter; in a diagram it appears as
 Java   -->  compiler -->    Java      --> Java interpreter
 source      (program)    "byte codes"     (program)
 code

For C programs, compilation has two conceptually separate steps. In a diagram it appears as

 C               C
 language   -->  preprocessor --> compiler --> assembly     etc. 
 source          (program)        (program)    language
 code

The C preprocessor does 3 important things. Within source code, each item that matters to the preprocessor is identified by the # (pound sign) at the beginning of a line.

  1. File inclusion, also called header files. Examples:
    
        #include <stdio.h>
        #include "allconstants.h"
    
    
    These files are included in the source code of the program. There will be needed definitions (of symbols and/or functions) within these files. File names enclosed within < and > characters cause the search for the file (like this standard I/O library file) to begin in a system-defined location. File names enclosed within double quote marks cause the search for the file to begin in the same directory as the source file being pre-processed.
  2. Macro substitution. Did you ever get tired of typing the same (relatively) long bit of code over and over? Macro substitution takes a fixed character sequence and substitutes it with another character sequence, often doing a little bit more that is really helpful, such as doing "the right thing" with parameters. It becomes the proper way to define a constant value in a C program. Here is a simple example:
    
        #define MAXITERATIONS 10000
    
    
    We use the string MAXITERATIONS in our source code, and we define it once within the source code. The preprocessor substitutes the integer value 10000 for every instance of this string within the source code. It is efficient (for code execution and for memory allocation). Another example, straight from Kernighan and Ritchie:
    
        #define max(A, B)  ((A) > (B) ? (A) : (B))
    
    
    With this, and the preprocessor understanding about parameters, we write source code
    
        x = max(y, z-4);
    
    
    and the preprocessor substitutes all the right values in all the right places. This is more efficient than implementing a function do the same thing. For every function call, it takes execution time to set up and return from the call.
    (Remember this when the course discusses function implementation in assembly language.)
  3. Conditional compilation. You will not need to know or understand this aspect of C for this class. However, read about it anyway in section 4.11.3 (second edition) of the Kernighan and Ritchie book. It essentially provides a way of defining a variable, such that based on the variable's value, a specific set of (source) code is or is not compiled into the resulting object code. The example in the Kernighan and Ritchie book is an excellent example of where conditional execution is often used in real programs. Code must often be different (do different things) to be correct when executing under different operating systems. When compiled for a target system (meaning that the operating system is defined) only the code intended specifically for that system is compiled in. This makes the code more general, and able to be compiled for more operating systems.

Copyright © Karen Miller, 2006,2007,2008