| I l @ ve RuBoard |
10.5 Advanced FeaturesThis book does not cover the complete list of C++ preprocessor directives. Among the more advanced features are an advanced form of the #if directive for conditional compilations and the #pragma directive for inserting compiler-dependent commands into a file. See your C++ reference manual for more information on these features. |
| I l @ ve RuBoard |
| I l @ ve RuBoard |
10.6 SummaryThe C++ preprocessor is a very useful part of the C++ language. It has a completely different look and feel from C++. However, it must be treated apart from the main C++ compiler.
Problems in macro definitions often do not show up where the macro is defined, but result in errors much further down in the program. By following a few simple rules, you can decrease the
Finally, if you got this far, be glad that the worst is over. |
| I l @ ve RuBoard |
| I l @ ve RuBoard |
10.7 Programming ExercisesNote that the solutions to all the exercises below can be obtained using standard C++ syntax such as inline and enum . In general, using C++ construction is preferred over using macro definitions. However since this is the chapter on the preprocessor, macros should be used for these exercises. Exercise 10-1: Create a set of macros to define a type called RETURN_STATUS and the following values: RETURN_SUCCESS , RETURN_WARNING , and RETURN_ERROR . Define a macro, CHECK_RETURN_FATAL,,, that takes a RETURN_STATUS as its argument and returns true if you have a fatal error.
Exercise 10-2:
Write a macro that returns true if its parameter is divisible by 10 and false
Exercise 10-3: Write a macro is_digit that returns true if its argument is a decimal digit. Write a second macro is_hex that returns true if its argument is a hex digit (0-9, A-F, a-f). The second macro should reference the first. Exercise 10-4: Write a preprocessor macro that swaps two integers. (If you're a real hacker, write one that does not use a temporary variable declared outside the macro.) |
| I l @ ve RuBoard |
| I l @ ve RuBoard |
10.8 Answers to Chapter QuestionsAnswer 10-1: After the program has been run through the preprocessor, the std::cout statement is expanded to look like: std::cout << "The square of all the parts is " << 7 + 5 * 7 + 5 << '\n';
The equation 7 + 5 * 7 + 5
#define ALL_PARTS (FIRST_PART + LAST_PART) the program executes correctly. Answer 10-2: The preprocessor is a very simple-minded program. When it defines a macro, everything past the identifier is part of the macro. In this case, the definition of MAX is literally =10 . When the for statement is expanded, the result is: for (counter==10; counter > 0; --counter) C++ allows you to compute a result and throw it away. For this statement, the program checks to see whether counter is 10 and discards the answer. Removing the = from the macro definition will correct the problem.
Answer 10-3:
As with the previous problem, the preprocessor does not respect C++ syntax conventions. In this case, the programmer used a semicolon to end the statement, but the preprocessor included it as part of the definition for
size = 10; -2;;
The two semicolons at the end do not hurt anything, but the one in the middle is a killer. This line
Answer 10-4: The output of the preprocessor looks like:
int main( ) {
int value;
value = 1;
if (value < 0)
std::cout << "Fatal Error: Abort\n"; exit(8);
std::cout << "We did not die\n";
return (0);
}
The problem is that two statements follow the if line. Normally they would be put on two lines. If we properly indent this program we get: Example 10-10. die3/die.cpp
#include <iostream>
#include <cstdlib>
int main( ) {
int value; // a random value for testing
value = 1;
if (value < 0)
std::cout << "Fatal Error:Abort\n";
exit(8);
std::cout << "We did not die\n";
return (0);
}
From this it is obvious why we always exit. The fact that there were two statements after the
if
was hidden by using a single preprocessor macro. The cure for this problem is to put curly braces around all
#define DIE \
{std::cout << "Fatal Error: Abort\n"; exit(8);}
Answer 10-5: The problem is that the preprocessor does not understand C++ syntax. The macro call: SQR(counter+1) expands to: (counter+1 * counter+1) The result is not the same as ((counter+1) * (counter+1)) . To avoid this problem, use inline functions instead of parameterized macros:
inline int SQR(int x) { return (x*x);}
If you must use parameterized macros, enclose each instance of the parameter in parentheses: #define SQR(x) ((x) * (x))
Answer 10-6:
The only difference between a parameterized macro and one without parameters is the parentheses immediately following the macro
(number) (1.0 / number) Removing the space between RECIPROCAL and (number) corrects the problem. |
| I l @ ve RuBoard |