Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!mips!pacbell.com!att!ucbvax!lynx.northeastern.edu!cschmidt From: cschmidt@lynx.northeastern.edu Newsgroups: comp.lang.c Subject: Re: A question on C programming style Message-ID: Date: 16 Apr 91 20:58:56 GMT Sender: usenet@ucbvax.BERKELEY.EDU Lines: 78 > How do the guru's on the net feel about the following two styles? > > [two examples, one of which uses nested include directives] My practice is to use nested include directives, but the technique I employ requires some explanation. This is a bit long, and I hope my fellow C programmers will find it of interest. Rather than writing header files directly, I write only .C files, then use a program I wrote that generates header files. This has several advantages, some of which have to do with include directives. The header generator program writes directives that prevent the compiler from including or interpreting a header file more than once when processing a single source file. o The program adds three lines to each output header file, enclosing the entire file in an "if" statement. This prevents the compiler from interpreting the same header file more than once. Example: #ifndef STDIO_H #define STDIO_H ... #endif o Every include directive written to the output header file is enclosed in an "if" statement. This prevents the compiler from including the same header file more than once. Example: #ifndef STDIO_H #include #endif Here is an important advantage of using this technique. A source file needs to include only the headers for modules that define things the source file uses directly. In other words, it is never necessary to include a header only to declare things required for the compiler to correctly interpret a header included subsequently. For example, if module A requires module B, and module B requires module C, then the module A source file only includes the B header explicitly. If the module B requirements are later modified, no changes to the modules that require B will be necessary. When you write module A, you do not need to know what module B requires. If module A happens to include header C before including header B, the conditional statements shown above prevent the compiler from opening header C twice. The header generator program encourages you to divide the input source file into two sections. (Actually, there are four section types in all, but this is enough complication for this message.) o Export section. This section contains the things that are copied to the output header file, such as include directives and other declarations for all other modules that use this module. A certain pragma directive marks the end of the export section. o Implementation section. This section contains the definitions (as opposed to the declarations) of exported variables and functions, and it may define non-exported constants, types, variables, and functions, and it may contain include directives that are required only for the implementation section. The header generator program takes an input file specification argument, which may include wildcards. For each specified source file, the program generates a header file only if there does not already exist a header file with a newer time stamp. An additional advantage: The compiler runs perceptably faster because the header files are compressed and because fewer header files are accessed. Note that a module does not include its own header file. Header file compression consists of removing all comments and blank lines, and replacing consecutive spaces and tabs with a single space. I would like to know what you all think about this. Christopher Schmidt cschmidt@lynx.northeastern.edu