* Scope of Macros
- Until #undef
- Or it is global static in current module
- Or it is global when included
* No Semicolon After Preprocessors
* Be cautious of the space in Macros
This example might not work as you expect:
#define max_(a, b) ((a) > (b) ? (a) : (b)) /* _ represents one space here */
* Arithmetic Calculation Is Allowed in Macro
#define SEC_PER_YEAR (60*60*24*365)UL
* Macros Are Not Functions
- Parenthese usage (the whole Macro and its oprands)
- Avoid evaluating operands more than once, like no such operators in operands, ++, --, etc.
* Macros Are Not Type Definitions
When declaring a new name for pointers, it is better off to use typedef instead of macros.
It is ok to
#define FOOTYPE struct foo
FOOTYPE a, b;
But this is not
#define FOOTYPE struct foo *
FOOTYPE a, b;
Meanwhile, this is allowed for macro but not for typedef:
#define FOOTYPE int
typedef int DOOTYPE;
unsigned FOOTYPE a;
unsigned DOOTYPE d; /* error */
* How to Define a Macro as An Expression?
It is desirous that macros could be used as a single statement and put a semicolon after them. A general solution for this is to use this structure:
do {\
...;\
...;\ /* No `break;' inside */
...;\
} while(0) /* No semicolon here */
Note: the new line is supposed to begin right after symbol \
A special case for this is if-else. The ?: and || could be used for simplicity due to its specific evaluation order of operands, like the definition of assert macro:
#define assert(exp) ((exp) || _assert_())
Here _assert_() is used to report errors.
* String in Macros
- #define str(s) (b = #s) =>
str(Hello); == b = "Hello";
* Function Parameters in Macro
- #define Print(x) (printf x) =>
print(("hello")); == printf("hello");
* ##
For example,
#define bwMCDR2_ADDRESS 4
#define bsMCDR2_ADDRESS 17
#define bmMCDR2_ADDRESS BIT_MASK(MCDR2_ADDRESS)
#define BIT_MASK(__bf) (((1U << (bw ## __bf)) - 1) << (bs ## __bf))
#define SET_BITS(__dst, __bf, __val) \
((__dst) = ((__dst) & ~(BIT_MASK(__bf))) | \
(((__val) << (bs ## __bf)) & (BIT_MASK(__bf))))
SET_BITS(MCDR2, MCDR2_ADDRESS, RegisterNumber);
* Misc
- #if, #elif, #else, #ifdef, #ifndef, #endif, #define, #undef
- #ifdef A; #if defined(A)||!defined(B)
- __LINE__(int), __FILE__(char *), __DATE__(char *), __TIME__(char *)
Reference:
Andrew Koenig, "C Traps and Pitfalls", AT&T Bell Lab
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment