Thinking in C++ Notes(9)

chapter 9: Inline function

2 problems with preprocessor macros:

  1. a macro looks like a function call, but doesn't always act like one.
  2. the preprocessor has no permission to access class member data. This means preprocessor macros can not be used as class member functions.

Processor pitfalls:

  • expression may expand inside the macro so that their evaluation precedence is different from what you expect.
    for example,

    #define FLOOR(x,b)  x>=b?0:1
        /* the macro will expand to */
        /* the precedence of & is lower than >=. */
        /* you can solve this problem by putting parentheses around everything in the macro definition. */
    #define FLOOR(x,b) (x)>=(b)?0:1

  • every time you use an argument in a macro, that argument is evaluated. so if the evaluation of an argument has side effects, then the result can be surprising and will definitely not mimic function behavior.

    #define BAND(x) (x)>5?(x):0
    /* after you call BAND(a++), a will be a+1 or a+2 */

Inline function

  • any function defined within a class body is automatically inline.
  • you will almost always want to put inline definitions in a header file.
  • you must include the header file containing the function and its definition in every file where the function is used.
  • you'd better not inline a big function.
  • the compiler cannot perform inlining if:
    1. the function is too complicated.(has any sort of looping)
    2. the address of the function is taken implicitly or explicitly

More preprocessor features:

  • stringizing: using # directive can turn an identifier into a character array.
  • string concatenation: two adjacent character arrays combine when they have no intervening punctuation.

    #define DEBUG(x)  cout<<#x" = "<<x<<endl

  • token pasting: using ## directive allows you take two identifiers and paste them together to create a new identifier.

    #define FIELD(a)  char* a##_string; int a##_size