-->

Previous | Table of Contents | Next

Page 455

CHAPTER 23

C and C++ Programming

by Robin Burk, revised by
David B. Horvath, CCP

IN THIS CHAPTER

Page 456

UNIX shells support a wide range of commands that can be combined, in the form of scripts, into reusable programs. Command scripts for shell programs (and utilities such as gawk and Perl) are all the programming that many UNIX users need in order to customize their computing environment.

Script languages have several shortcomings, however. To begin with, the commands that a user types into a script are read and evaluated only when the script is being executed. Interpreted languages are flexible and easy to use, but they are also inefficient because the commands must be reinterpreted each time the script is executed. Interpreted languages are also ill-suited to manipulate the computer's memory and I/O devices directly. Therefore, the programs that process scripts (such as the various UNIX shells, the awk utility, and the Perl interpreter) are themselves written in the C and C++ languages, as is the UNIX kernel.

Many users find it fairly easy to learn a scripted, interpreted language because the commands can usually be tried out one at a time, with clearly visible results. Learning a language such as C or C++ is more complex and difficult because you must learn to think in terms of machine resources and the way in which actions are accomplished within the computer, rather than in terms of user-oriented commands.

This chapter introduces you to the basic concepts of C and C++ and demonstrates how to build some simple programs. Even if you don't go on to learn how to program extensively in either language, you will find that the information in this chapter will help you to understand how kernels are built and why some of the other features of UNIX work the way they do. Additional resources are listed at the end of the chapter in the section "Additional Resources."

Introduction to C

C is the programming language most frequently associated with UNIX. Since the 1970s, the bulk of the operating system and its applications have been written in C. Because the C language doesn't directly rely on any specific hardware architecture, UNIX was one of the first portable operating systems. In other words, the majority of the code that makes up UNIX doesn't know and doesn't care about knowing what computer it is actually running on. Machine-
specific features are isolated in a few modules within the UNIX kernel, which makes it easy for you to modify these when porting to a different hardware architecture.

C was first designed by Dennis Ritchie for use with UNIX on DEC PDP-11 computers. The language evolved from Martin Richard's BCPL, and one of its earlier forms was the B language, which was written by Ken Thompson for the DEC PDP-7. The first book on C was The C Programming Language by Brian Kernighan and Dennis Ritchie and was published in 1978.

In 1983, the American National Standards Institute (ANSI) established a committee to
standardize the definition of C. The resulting standard is known as ANSI C, and it is the recognized standard for the language grammar and a core set of libraries. The syntax is slightly different from the original C language, which is frequently called K&R—for Kernighan and Ritchie. In this chapter, I will primarily address ANSI C.

Page 457

Programming in C: Basic Concepts

C is a compiled, third-generation procedural language. Compiled means that C code is analyzed, interpreted, and translated into machine instructions at some time prior to the execution of the C program. These steps are carried out by the C compiler and, depending on the complexity of the C program, by the make utility. After the program is compiled, it can be executed over and over without recompilation.

The phrase third-generation procedural describes computer languages that clearly distinguish the data used in a program from the actions performed on that data. Programs written in third-generation languages take the form of a series of explicit processing steps, or procedures, which manipulate the contents of data structures by means of explicit references to their location in memory and which manipulate the computer's hardware in response to hardware interrupts.

Functions in C Programs

In the C language, all procedures take the form of functions. Just as a mathematical function transforms one or more numbers into another number, a C function is typically a procedure that transforms some value or performs some other action and returns the results. The act of invoking the transformation is known as calling the function.

Mathematical function calls can be nested, as can function calls in C. When function calls are nested, the results of the innermost function are passed as input to the next function, and so on. Table 23.1 shows how nested calls to the square root function are evaluated arithmetically.

Table 23.1. Nested operations in mathematics.


Function Value
sqrt(256) 16
sqrt( sqrt(256) ) = sqrt(16) 4
sqrt( sqrt( sqrt(256) ) ) = sqrt(4) 2

Figure 23.1 shows the way that function calls are nested within C programs. In the figure, the Main function calls Function 1, which calls Function 2. Function 2 is evaluated first, and its results are passed back to Function 1. When Function 1 completes its operations, its results are passed back to the Main function.

Nonfunctional procedures in other languages often operate on data variables that are shared with other code in the program. For instance, a nonfunctional procedure might update a programwide COUNT_OF_ERRORS whenever a user makes a keyboard mistake. Such procedures must be carefully written, and they are usually specific to the program for which they were first created because they reference particular shared data variables within the wider program.

A function, however, receives all the information it needs (including the location of data variables to use in each instance) when it is called. The function neither knows nor cares about the

Previous | Table of Contents | Next