Part I: Macro basics
A macro is simply a text substitution tool in the C preprocessing phase, which is not visible to binary code after compilation. The basic usage is as follows:
1. Identifier aliases
#define BUFFER_SIZE 1024
preprocessing phase,
Foo = (char *) malloc (buffer_size);//is replaced with foo = (char *) malloc (1024);
Macro body wrapping requires a backslash at the end of the line
#define NUMBERS 1, 2, 3
preprocessing phase
int x[] = {numbers};//is expanded to int x[] = {1, 2, 3};
2. Macro functions
Macros with parentheses after the macro name are considered to be macro functions. The usage is the same as the normal function, except in the preprocessing phase, the macro function is expanded. The advantage is that there is no common function to save the register and the cost of parameter passing, the expanded code is conducive to CPU cache utilization and command prediction, fast. The disadvantage is that the executable code is large in size.
#define MIN (x, y) ((x) < (y)? (X): (y)) y = min;//will be expanded to Y = ((1) < (2)? (1): (2));
Part Two: Special usage of macros
1. String
In the macro body, if you add a # to the macro parameter, the macro will be expanded to form a string when the macro body expands. Such as:
#define WARN_IF (exp) do {IF (exp) fprintf (stderr, "Warning:" #EXP "\ n");} while (0)
warn_if (x = = 0); will be expanded into:
#define WARN_IF (exp) do {IF (exp) fprintf (stderr, "Warning:" "x = = 0" "\ n");} while (0)
This usage can be used in assert, if the assertion fails, you can output the failed statement to the feedback information
2. Connect
In the macro body, if there is a # # in the identifier of the macro body, the macro parameters are replaced directly in the identifier when the macro body expands. Such as:
#define COMMAND (name) {#NAME, name # # _command}struct command{Char *name; void (*function) (void);};
When the macro is expanded
struct command commands[] = {command (quit), command (Help), ...};//will be expanded to: struct command commands[] = {{"qui T ", Quit_command}, {" Help ", Help_command}, ...};
High-level usage of macros and several common pits
1. Grammatical problems
Because it is a plain text substitution, the C preprocessor does not make any syntax checks on the macro body, such as missing parentheses, fewer semicolons, or whatever. Here to be extra careful, this may lead to a variety of wonderful problems, it is difficult to find the root cause.
2. Operator precedence Issues
Not only is the macro body a plain text replacement, but the macro parameter is also a plain text replacement. Here's a simple macro that implements multiplication:
#define MULTIPLY (x, y) x*y
MULTIPLY no problem, it will normally unfold into 1*2. The problem is that this expression multiply (1+2, 3), expanded to become the 1+2, obviously the priority is wrong. In the macro body, you can avoid this problem by adding parentheses to the referenced parameters.
#define MULTIPLY (x, y) (x) * (y)
MULTIPLY (1+2, 3) will be expanded to (1+2) * (3) and the priority level is normal. In fact, this problem and some of the problems mentioned below are due to the semantic destruction caused by the replacement of pure text, to be extra careful.
3. Semicolon engulfing problem
The following macro definitions are available:
Macros in the C language