Tuesday, October 20, 2009

10.2 Conditional Compilation




I l@ve RuBoard










10.2 Conditional Compilation





One problem programmers have is
writing code that can work on many different machines. In theory, C++
code is portable; in practice, many machines have little quirks that
must be accounted for. For example, this book covers Unix, MS-DOS,
and Windows compilers. Although they are almost the same, there are
some differences.



Through the use of conditional
compilation, the preprocessor allows you great
flexibility in changing the way code is generated. Suppose you want
to put debugging code in the program while you are working on it and
then remove the debugging code in the production version. You could
do this by including the code in an #ifdef-#endif section, like this:



#ifdef DEBUG 
std::cout << "In compute_hash, value " << value << " hash " << hash << "\n";
#endif /* DEBUG */









You do not have to put the /* DEBUG */ after the
#endif, but it is very useful as a
comment.




If the beginning of the program contains the following directive, the
std::cout is included:



#define DEBUG       /* Turn debugging on */ 


If the program contains the following directive, the
std::cout is omitted:



#undef DEBUG        /* Turn debugging off */ 


Strictly speaking, the #undef DEBUG is
unnecessary. If there is no #define DEBUG
statement, DEBUG is undefined. The #undef
DEBUG
statement is used to indicate explicitly to anyone
reading the code that DEBUG is used for
conditional compilation and is now turned off.



The directive #ifndef causes the
code to be compiled if the symbol is not
defined:



#ifndef STACK_SIZE /* Is stack size defined? */
#define STACK_SIZE 100 /* It's not defined, so define it here */
#endif /* STACK_SIZE */


#else reverses the sense of the
conditional. For example:



#ifdef DEBUG 
std::cout << "Test version. Debugging is on\n";
#else /* DEBUG */
std::cout << "Production version\n";
#endif /* DEBUG */


A programmer may wish to temporarily remove a section of code. A
common method of doing this is to comment out the code by enclosing
it in /* */. This can cause problems, as shown by the following
example:



/***** Comment out this section 
section_report( );
/* Handle the end-of-section stuff */
dump_table( );
**** End of commented out section */


This generates a syntax error for the fifth line. Why? Because the */
on the third line ends the comment that started on the first line,
and the fifth line :



**** End of commented out section */ 


is not a legal C++ statement.



A better method is to use the #ifdef
construct to remove the code.



#ifdef UNDEF 
section_report( );
/* Handle the end-of-section stuff */
dump_table( );
#endif /* UNDEF */


(Of course the code will be included if anyone defines the symbol
UNDEF; however, anyone who does so should be
shot.)



The compiler switch
-Dsymbol allows symbols to be defined on the
command line. For example, the command:



CC -DDEBUG -g -o prog prog.cc 


compiles the program prog.c and includes all the
code in #ifdef DEBUG/#endif /* DEBUG */ pairs,
even though there is no #define DEBUG in the
program. The Borland-C++ equivalent is:



bcc32 -DDEBUG -g -N -eprog.exe prog.c 


The general form of the option is -Dsymbol or
-Dsymbol=value. For
example, the following sets MAX to 10:



CC -DMAX=10 -o prog prog.c 


Most C++ compilers automatically define some system-dependent
symbols. For example, Borland-C++ defines the symbol _
_BORLANDC_ _,
and Windows-based compilers define _
_WIN32
. The ANSI standard compiler C defines the symbol
_ _STDC_ _. C++ compilers define the symbol
_ _cplusplus. Most Unix compilers define a name
for the system (e.g., Sun, VAX, Linux, etc.); however, they are
rarely documented. The symbol unix is always
defined for all Unix machines










Command-line options specify the initial value of a symbol only. Any
#define and #undef directives
in the program can change the symbol's value. For
example, the directive #undef DEBUG results in
DEBUG being undefined whether or not you use
-DDEBUG .










    I l@ve RuBoard



    No comments:

    Post a Comment