Previous: 3.3.2 Macros
Up: 3.3 Coding Programs for Readability
Next: 3.3.4 Conditional Compilation
Previous Page: 3.3.2 Macros
Next Page: 3.3.4 Conditional Compilation
The second feature provided by the preprocessor allows us to break our source files into smaller pieces to be reassembled at compile time. Using functions to hide details of algorithms and macros to hide the syntax and ``magic numbers'' to make our programs more readable often results in many function prototype statements and macro definitions at the beginning of source code files. These may also be hidden in separate files, and included in the source file by the preprocessor. The files containing this information to be included are called include files or header files, and by convention, are named with a .h extension on the file name. Header files are also often used to provide common macro definitions and prototype statements that may be useful in may programs (or as we shall see later, in many files making up a single program). An example of the later case are the standard library functions provided in C; the prototype statements for these functions should be available to any program which chooses to use the functions. In many of our programs so far, we have used the library functions printf() and scanf(). Where are the prototypes for these? As well as providing the code for library functions, all standard C implementations provide a set of .h files with this information. The file stdio.h contains the prototypes and macros needed to use the I/O library. (We have not needed this file before because the compiler will make assumptions about functions if prototypes are not provided. Sometimes these assumptions are ``safe'', but often they are not. It is a good idea, from now on, to include stdio.h in any program using the I/O library).
The statements and directives in an include file are inserted in a source file when the preprocessor encounters an #include directive in the original source file. To include stdio.h the directive is:
#include <stdio.h>The angle brackets, < and >, surrounding the filename indicate to the preprocessor that the file, stdio.h, is to be found in ``the usual place'' where standard header files are kept on the system (this is system dependent), and its contents placed in the source code in place of the #include directive. Any other directives within the included file (such as #define or other #include directives) are also processed at this time.
Besides the standard header files, as a programmer you can create and include your own header files for your programs. For example, in our niceday.c program, we defined macros for TRUE and FALSE. These macros are very common in many programs, so it would be convenient if we could enter those definitions in a single header file and simply include that header file in any program the uses those macros. This header file might be called tfdef.h and contain:
/* File: tfdef.h
Programmer: Programmer Name
This file contains the definitions of TRUE and FALSE
*/
#define TRUE 1
#define FALSE 0
To include these definitions in a .c source file, use the directive:
#include "tfdef.h"Notice in this instance that the file name is surrounded by double quote, ", characters rather than the angle brackets used before. This syntax tells the preprocessor that the header file is to be found in the same directory as the .c source file currently being processed.
Again, in our nice day program, all of the other macro definitions and prototypes relating just to this program may also be placed in a header file, say niceday.h:
/* File: niceday.h
Programmer: Programmer Name
This file contains the definitions of macros and prototypes
for functions used by the niceday program.
*/
#define TOO_COLD 80
#define TOO_HOT 90
#define HOT_DAY(t) ((t) > TOO_HOT)
#define COLD_DAY(t) ((t) < TOO_COLD)
#define ANY_DAYS(n,b) (((n) + (b)) > 0)
int nice_day(int temp);
int print_results(int nice, int bad, int temp_sum);
and replaced in niceday.c with:
#include "niceday.h"Thus, the beginning of niceday.c has been reduced to:
/* File: niceday.c
Programmer: Programmer Name
Date: Current Date
This program counts the number of nice days in a set of high
temperature data.
*/
#include <stdio.h>
#include "tfdef.h"
#include "niceday.h"
main()
{ ...
Notice we include stdio.h at the head of the source file. Its contents are
available for use by the entire source file. We also declare the function
prototypes for nice_day() and print_results() in the file niceday.h
outside main(). A declaration outside a function is
called an external declaration. The scope of an external declaration is the
entire file from the point of the declaration; i.e. all code that follows the
external declaration can use the declared item. Since stdio.h is included
outside main(), the declarations for scanf() and printf() are also external.
External declaration of functions is convenient since it avoids repeated
declarations of the same function. On the other hand, external declarations of
variables leads to poorly structured programs and destroys modularity of
functions. External declarations of variables is strongly discouraged.
In summary, the syntax of the #include directive is: