5. The C Preprocessor
 
5.1 File Inclusion
 
If the filename is quoted, searching for the file typically begins where the source program was found;    if it is not found there, or if the name is enclosed in < and >, searching follows an implementation-
   defined rule to find the file. An included file may itself contain #include lines.
 
#include “filename”

or

#include <filename>
 
5.2 Conditional Inclusion
 
It is possible to control preprocessing itself with conditional statements that are evaluated during   preprocessing.
The #if, #ifdef, #ifndef, #else, #elif and #endif directives can be used for conditional compilation.
 
  Example
#if !defined(HDR)
#define HDR
...
#endif
#if SYSTEM == BSD
    #define HDR “bsd.h”
#elif SYSTEM == MSDOS
    #define HDR “msdos.h”
#else
    #define HDR “default.h”
#include HDR
 
The #ifdef and #ifndef lines are specialized forms that test whether a name is defined.
 
#ifdef __unix__
    #include <unistd.h>
#elif defined _WIN32
/* _WIN32 is defined by most compilers */
    # include <windows.h>
#endif
 
5.3 Macro Substitution
 
5.3.1 Standard Predefined Positioning Macros
 
  There are two types of macros, object-like and function-like. Object-like macros do not take parameters; function-like macros do. The generic syntax for declaring an identifier as a macro of each type is, respectively,
 
// object-like macro
#define <identifier> <replacement token list>
#define PI 3.141592

// function-like macro, note parameters
#define <identifier>(<parameter list>) <replacement token list>
#define MAX(A, B) ((A) > (B) ? (A) : (B))
 
5.3.2 Precedence
 
  Macro defined as
x = MAX(p+q, r+s);

will expand

x = ((p+q) > (r+s) ? (p+q) : (r+s));
 
– Notice: If the expression MAX(++firstnum, secondnum) is evaluated, then firstnum may be    incremented twice, not once as would be expected.
– Some care also has to be taken with parentheses to make sure the order of evaluation is preserved;    consider what happens when the macro
 
#define SQ(x) x*x /* WRONG */

is invoked as SQ(z+1).
 
5.3.3 Token Concatenation
 
  Token concatenation, also called token pasting, is one of the most subtle — and easy to abuse — features of the C macro preprocessor. Two arguments can be 'glued' together using ## preprocessor operator; this allows two tokens to be concatenated in the preprocessed code.
 
#define MYCASE(item, id) \
case id: \
    item##_##id = id;\
break

switch(x) {
     MYCASE(widget, 23);
}

The line MYCASE(widget, 23); gets expanded here into
case 23:
     widget_23 = 23;
break;
 
5.3.4 Semicolons
 
  One stylistic note about the above macro is that the semicolon on the last line of the macro definition is omitted so that the macro looks 'natural' when written. It could be included in the macro definition, but then there would be lines in the code without semicolons at the end which would throw off the casual reader.
 
  The following example causes errors in control flow blocks:
#define PRETTY_PRINT(msg) printf(msg);

   if (n < 10)
     PRETTY_PRINT("n is less than 10");
   else
     PRETTY_PRINT("n is at least 10");
 
5.3.5 Multiple Statements
 
  Inconsistent use of multiple-statement macros can result in unintended behavior.
#define CMDS \
    a = b; \
    c = d;

if (var == 13)
    CMDS;
else
    return;
 
  The do and while (0) are needed to allow the macro invocation to be followed by a semicolon.

#define CMDS \
   do { \
      a = b; \
      c = d; \
    } while (0)

 
#define CMDS \
   ({ \
     a = b; \
     c = d; \
    })
 
5.3.6 Quoting Macro Arguments
 
  Although macro expansion does not occur within a quoted string, the text of the macro arguments can be quoted and treated as a string literal by using the "#" directive (also known as the "Stringizing Operator"). For example, with the macro
#define QUOTEME(x) #x
printf(“%s\n”, QUOTEME(1+2));

will expand to

printf(“%s\n”, “1+2”);
 
5.4 pragma once
 
  In the C and C++ programming languages, #pragma once is a non-standard but widely supported preprocessor directive designed to cause the current source file to be included only once in a single compilation. Thus, #pragma once serves the same purpose as #include guards, but with several advantages, including: less code, avoiding name clashes, and improved compile speed.
File “grandfather.h”
#pragma once
int member;

File “father.h”
#include “gradfather.h”

File “child.c”
#include “gradfarther.h”
#include “father.h”
 
5.5 Predefined Names
 
  Several identifiers are predefined, and expand to produce special information. They, and also the preprocessor expansion operator defined, may not be undefined or redefined.
__LINE__ A decimal constant containing the current source line number
__FILE__ A string literal containing the name of the file being compiled.
__DATE__ A string literal containing the date of compilation, in the form “mm dd yyyy”
__TIME__ A string literal containing the time of compilation, in the form “hh:mm:ss”
__STDC__ The constant 1. It is intended that this identifier be defined to be 1 only in standard conforming implementations.
 
 
 
이전페이지 / 6 / 다음페이지