Prev Next

Modules

Breaking a program into modules

Programs are usually build from several modules. You typically break each module into two files:

  1. an implementation file (with extension .cpp or .cc for a C++ program, or .c for a C program) that holds the details of how things work;

  2. a header file (with extension .h), telling other modules about the features that this module provides.

If there is a function in the code file that other files should be able to use, then there should be a prototype of that function in the header file. If there is a variable in the code file that other files should know about, then there is an extern declaration in the header file.

Here is an example of a pair of files. They must be in two different files. These should not be taken as a recommendation on how to write functions: realistically, char_to_count should be a parameter to function count_chars.

// File: count.h
//
// count_chars(str) returns the number of 
// times that character char_to_count occurs
// in null-terminated string str.

extern char char_to_count;
int count_chars(char* str);
// File: count.cpp

#include "count.h"

char char_to_count;

// count_chars(str) returns the number 
// of times that character char_to_count 
// occurs in null-terminated string str.

int count_chars(char* str)
{
  int count = 0;
  char* p;

  for(p = str; *p != 0; p++) {
    if(*p == char_to_count) count++;
  }
  return count;
}

When you compile your files, you produce object files, with extension .o or .obj. (This use of the term "object" is unrelated to the use of the same term in object-oriented programming.) You then run a linker to link the object files together into a single executable file.

Exporting arrays

If you declare an array in a module, as in

int A[30];
then the extern declaration should have the same form, but need not include the size. For example, you might write
extern int A[];

An array is a pointer constant. Do not put

extern int* A;
since that tells the compiler that A is a pointer variable, and causes confusion.

The main program

When the linker builds an executable file, it looks for a function of a specific, and creates the executable file so that it starts with that function. In most systems, the function to start with is called main. The main function has three parameters, although you often use only the first two. When you use two, your main program heading looks like this.

 int main(int argc, char* argv[])
where array argv holds the parts of the command line that was used to invoke this program, and argc is the number of members of argv. argv[0] is the name of the command. If you type command
myprog -d test.txt

then argc is 3 and argv is as follows.
  argv[0] = "myprog"
  argv[1] = "-d"
  argv[2] = "test.txt"
The result returned by main is the exit status of the program. Normally, it is 0. A nonzero value indicates that an error occurred during the program's execution.

If you do not use the parameters argc and argv, you can omit them, and write

 int main()

Building software

Integrated development environments provide features, usually called projects, for linking several modules together into a single executable program. An approach to the same thing that is more versatile, and that does not require an integrated development environment, is a makefile.

A makefile gives information telling how each part of a system depends on other parts, and tells how to build the system. The following is a sample makefile. It builds an executable program called go from two modules, main.cc and stuff.cc.

File makefile
COMPILE      = g++
LINK         = g++
COMPILEFLAGS = -c -Wall
LINKFLAGS    = 

main: stuff.o main.o
	$(LINK) -o main $(LINKFLAGS) stuff.o main.o

stuff.o: stuff.cc stuff.h
	$(COMPILE) $(COMPILEFLAGS) stuff.cc

main.o: main.cc stuff.h
	$(COMPILE) $(COMPILEFLAGS) main.cc

clean: 
	$(RM) main stuff.o main.o

The makefile defines variables (COMPILE, etc) that stand for strings. In the body, $(COMPILE) is replaced by g++.

The makefile defined targets main, stuff.o, main.o and clean. Each target is followed, on the same line, by a list of the things that target depends on. If any of those things are modified, then this target must be rebuilt. After that is a line (or lines) beginning with a tab, giving a command (or commands) that will build the target.

To build main, you type command

  make main
Make will run all of the necessary commands.

The target clean is not really something to be built. Running it removes all of the machine-generated files. If you want to rebuild everyting, you type

  make clean
  make main


Prev Next