Since the rand and bubble_sort functions in the program above are useful, you will probably want to reuse them in other programs you write. You can put them into a utility library to make their reuse easier.
Every library consists of two parts: a header file and the actual code file. The header file, normally denoted by a .h suffix, contains information about the library that programs using it need to know. In general, the header file contains constants and types, along with headers for functions available in the library. Enter the following header file and save it to a file named util.h.
/* util.h */
extern int rand();
extern void bubble_sort(int,int []);
These two lines should remind you of function prototypes. The word "extern" in C represents functions that will be linked in later. In an old-style compiler, remove the parameters from the parameter list of bubble_sort.
Enter the following code into a file named util.c.
/* util.c */
#include "util.h"
int rand_seed=10;
int rand()
/* from K&R - produces a random number between 0 and 32767.*/
{
rand_seed = rand_seed * 1103515245 +12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
void bubble_sort(int m,int a[])
{
int x,y,t;
for (x=0; x < m-1; x++)
for (y=0; y < m-x-1; y++)
if (a[y] > a[y+1])
{
t=a[y];
a[y]=a[y+1];
a[y+1]=t;
}
}
Note that the file includes its own header file (util.h) and that it uses quotes instead of the symbols <> , which are used only for system libraries. As you can see, this looks like normal C code. Note that the variable rand_seed, because it is not in the header file, cannot be seen or modified by a program using this library. This is called information hiding. Adding the word static in front of int enforces the hiding completely.
Enter the following main program in a file named main.c.
#include
#include "util.h"
#define MAX 10
int a[MAX];
void main()
{
int i,t,x,y;
/* fill array */
for (i=0; i < MAX; i++)
{
a[i]=rand();
printf("%d\n",a[i]);
}
bubble_sort(MAX,a);
/* print sorted array */
printf("--------------------\n");
for (i=0; i < MAX; i++)
printf("%d\n",a[i]);
}
This code includes the utility library. The main benefit of using a library is that the code in the main program is much shorter.
Compiling and Running with a Library
To compile the library, type the following at the command line (assuming you are using UNIX):
cc -c -g util.c
The -c causes the compiler to produce an object file for the library. The object file contains the library's machine code. It cannot be executed until it is linked to a program file that contains a main function. The machine code resides in a separate file named util.o.
To compile the main program, type the following:
cc -c -g main.c
This line creates a file named main.o that contains the machine code for the main program. To create the final executable that contains the machine code for the entire program, link the two object files by typing the following:
cc -o main main.o util.o
which links main.o and util.o to form an executable named main. To run it, type main.
It can be cumbersome to type all of the cc lines over and over again, especially if you are making a lot of changes to the code and it has several libraries. The make facility solves this problem. You can use the following makefile to replace the compilation sequence above:
main: main.o util.o
cc -o main main.o util.o
main.o: main.c util.h
cc -c -g main.c
util.o: util.c util.h
cc -c -g util.c
Enter this into a file named makefile, and type make to build the executable. Note that you must precede all cc lines with a tab. (Eight spaces will not suffice---it must be a tab. All other lines must be flush left.)
This makefile contains two types of lines. The lines appearing flush left are dependency lines. The lines preceded by a tab are executable lines, which can contain any valid UNIX command. A dependency line says that some file is dependent on some other set of files. For example, main.o: main.c util.h says that the file main.o is dependent on the files main.cand util.h. If either of these two files changes, the following executable line(s) should be executed to recreate main.o.
Note that the final executable produced by the whole makefile is main, on line 1 in the makefile. The final result of the makefile should always go on line 1, which in this makefile says that the file main is dependent on main.o and util.o. If either of these changes, execute the line cc -o main main.o util.o to recreate main.
It is possible to put multiple lines to be executed below a dependency line---they must all start with a tab. A large program may have several libraries and a main program. The makefile automatically recompiles everything that needs to be recompiled because of a change.
Every library consists of two parts: a header file and the actual code file. The header file, normally denoted by a .h suffix, contains information about the library that programs using it need to know. In general, the header file contains constants and types, along with headers for functions available in the library. Enter the following header file and save it to a file named util.h.
/* util.h */
extern int rand();
extern void bubble_sort(int,int []);
These two lines should remind you of function prototypes. The word "extern" in C represents functions that will be linked in later. In an old-style compiler, remove the parameters from the parameter list of bubble_sort.
Enter the following code into a file named util.c.
/* util.c */
#include "util.h"
int rand_seed=10;
int rand()
/* from K&R - produces a random number between 0 and 32767.*/
{
rand_seed = rand_seed * 1103515245 +12345;
return (unsigned int)(rand_seed / 65536) % 32768;
}
void bubble_sort(int m,int a[])
{
int x,y,t;
for (x=0; x < m-1; x++)
for (y=0; y < m-x-1; y++)
if (a[y] > a[y+1])
{
t=a[y];
a[y]=a[y+1];
a[y+1]=t;
}
}
Note that the file includes its own header file (util.h) and that it uses quotes instead of the symbols <> , which are used only for system libraries. As you can see, this looks like normal C code. Note that the variable rand_seed, because it is not in the header file, cannot be seen or modified by a program using this library. This is called information hiding. Adding the word static in front of int enforces the hiding completely.
Enter the following main program in a file named main.c.
#include
#include "util.h"
#define MAX 10
int a[MAX];
void main()
{
int i,t,x,y;
/* fill array */
for (i=0; i < MAX; i++)
{
a[i]=rand();
printf("%d\n",a[i]);
}
bubble_sort(MAX,a);
/* print sorted array */
printf("--------------------\n");
for (i=0; i < MAX; i++)
printf("%d\n",a[i]);
}
This code includes the utility library. The main benefit of using a library is that the code in the main program is much shorter.
Compiling and Running with a Library
To compile the library, type the following at the command line (assuming you are using UNIX):
cc -c -g util.c
The -c causes the compiler to produce an object file for the library. The object file contains the library's machine code. It cannot be executed until it is linked to a program file that contains a main function. The machine code resides in a separate file named util.o.
To compile the main program, type the following:
cc -c -g main.c
This line creates a file named main.o that contains the machine code for the main program. To create the final executable that contains the machine code for the entire program, link the two object files by typing the following:
cc -o main main.o util.o
which links main.o and util.o to form an executable named main. To run it, type main.
It can be cumbersome to type all of the cc lines over and over again, especially if you are making a lot of changes to the code and it has several libraries. The make facility solves this problem. You can use the following makefile to replace the compilation sequence above:
main: main.o util.o
cc -o main main.o util.o
main.o: main.c util.h
cc -c -g main.c
util.o: util.c util.h
cc -c -g util.c
Enter this into a file named makefile, and type make to build the executable. Note that you must precede all cc lines with a tab. (Eight spaces will not suffice---it must be a tab. All other lines must be flush left.)
This makefile contains two types of lines. The lines appearing flush left are dependency lines. The lines preceded by a tab are executable lines, which can contain any valid UNIX command. A dependency line says that some file is dependent on some other set of files. For example, main.o: main.c util.h says that the file main.o is dependent on the files main.cand util.h. If either of these two files changes, the following executable line(s) should be executed to recreate main.o.
Note that the final executable produced by the whole makefile is main, on line 1 in the makefile. The final result of the makefile should always go on line 1, which in this makefile says that the file main is dependent on main.o and util.o. If either of these changes, execute the line cc -o main main.o util.o to recreate main.
It is possible to put multiple lines to be executed below a dependency line---they must all start with a tab. A large program may have several libraries and a main program. The makefile automatically recompiles everything that needs to be recompiled because of a change.
No comments:
Post a Comment