Modular Programming in C http://www.embedded.com/shared/printableArticle.jhtml?articleID=9...
1 of 6 11/4/05 12:30 AM
Modular Programming in C
By John R. Hayes, Courtesy of Embedded Systems Programming
Nov 30 2001 (8:24 AM)
URL: http://www.embedded.com/showArticle.jhtml?articleID=9900399
Separating interface from implementation has many practical benefits. Here's a simple way to do
just that, in ANSI-standard C code.
How do you organize medium-sized or larger C programs? Few C textbooks give any insight; they
concentrate on exposition of C's features using small examples. The examples usually fit in a single source
code file. Without some guiding principle of organization, larger C programs can become difficult to
understand and impossible to maintain. Modular programming is one way of managing the complexity.
Modular programming groups related sets of functions together into a module. The module is divided into an
interface and an implementation. The module exports the interface; clients modules import the interface so
that they can access the functions in the module. The implementation of the module is private and hidden
from the view of clients. The division of programs into modules is a powerful organizing principle for
designing non-trivial programs. Modules provide abstraction, encapsulation, and information-hiding, making
the large-scale structure of a program easier to understand. Careful design of modules also promotes
software reuse, even in embedded systems programming.
Unfortunately, C does not explicitly support modular programming. The archetypal modular programming
language is Nicklaus Wirth's Modula-2 (and -3). A modular language, such as Modula, has syntax for
separating the implementation from the interface and for importing modules. Conveniently, some of C's
features, both in the language and the pre-processor, can be co-opted into providing Modula-like capabilities.
These features, in conjunction with a set of conventions, make modular programming in C a practical and
effective technique.
Modular programming
Programmers work with abstractions every day. An abstraction highlights the essential features of
something while ignoring its details. An abstraction could encompass a piece of hardware, a software
component, and so on. For example, a serial port can be abstracted to a pair of functions for reading and
writing bytes to the port; the details of the UART, its registers and addresses, are suppressed. For our
purposes, the interface to a module is an abstraction of the module's functions. The interface defines the
features of the module and how to use them.
The programmer using a module sees the module's interface definition. On the other side of this interface is
the module's implementation. The programmer should not use anything in the implementation that is not
defined in the interface. Ideally, the module should ensure that the programmer cannot access the internals
of the implementation. Such information-hiding is the only way that an implementation can protect the
integrity of its data and guarantee the module's correctness. Hiding the implementation also allows an
improved implementation to be substituted without affecting anything outside the module.
The two most important elements of a module are the division of the module into an interface and an
implementation and the ability to hide information in the implementation. A syntax for creating a module
(similar to that of Modula) would be: