4. Preprocessors

Preprocessors can behave differently in several ways. For those who need them, there are good publicly available preprocessors that are ANSI C-compliant. One such preprocessor is the one distributed with the X Window System developed by the MIT X Consortium.

4.1. Command Options

The interpretation of the -I command option can differ from one system to another. Besides, it is not covered by the Standard. For example, the directive #include "dir/file.h" in conjunction with -I.. would cause most preprocessors in a Unix-like environment to search for file.h in ../dir, but under VMS, file.h is only searched for in the subdirectory dir in the current working directory.

4.2. #pragma and #elif

Directives are very much the same in all preprocessors, except that some preprocessors may not know about the defined operator in a #if directive nor about the #pragma and #elif directives.

The #pragma directive should pose no problems even to old preprocessors if it comes indented. (4) Furthermore, it is advisable to enclose them with #ifdefs in order to document under which platform they make sense:

#ifdef <platform-specific-symbol>
   #pragma ...
#endif

Beware of #pragma directives that alter the semantics of the program and consider the case when they are not recognized by a particular compiler. Evidently, if the behavior of the program relies on their correct interpretation then, in order for the program to be portable, all target platforms must recognize them properly.

4.3. Concatenation

Concatenation of symbols has two variants. One is the old K&R [9] style that simply relied on the fact that the preprocessor substituted comments such as /**/ for nothing. Obviously, that does not result in concatenation if the preprocessor includes a space in the output. The ANSI C Standard defines the operators ## and (implicit) concatenation of adjacent strings. Since both styles are a fact of life it is useful to include the following in one's header files: (5)

#ifdef  __STDC__
#  define  GLUE(a,b)  a##b
#else
#  define  GLUE(a,b)  a/**/b
#endif

If needed, one could define similar macros to GLUE several arguments. (6)

4.4. Token Substitution

Some preprocessors perform token substitution within quotes while others do not. Therefore, this is intrinsically non-portable. The Standard disallows it but provides a mechanism to obtain the same results. The following should work with ANSI-compliant preprocessors or with the ones that perform token substitution within quotes:

#ifdef  __STDC__
#  define  MAKESTRING(s)  # s
#else
#  define  MAKESTRING(s)  "s"
#endif

4.5. Miscellaneous


4. Old preprocessors only take directives that begin with # in the first column.

5. Some have suggested using #if __STDC__ instead of simply #ifdef __STDC__ to test if the compiler is ANSI-compliant because of compilers that are not, but define __STDC__ equal to zero.

6. GLUE(a,GLUE(b,c)) would not result in the concatenation of a, b, and c.


upcontents previousStandardization Efforts nextThe Language