Macro definition of C Language notes
(1) Symbolic Constants
Macro definition is a replacement strategy in C language, that is, using preprocessing commands # define equals a string of (lengthy) texts with a name (macro, then you can batch use Macros in the source code. In the preprocessing phase, replace the macro in the source code with the original text. For example, in the source code:
#define PI 3.14
In the following code, you can directly replace PI with 3.14 of the Code to be written. During preprocessing, all the PI values are changed back to 3.14.
What are the benefits of this exchange? If all the 3.14 values in the Code need to be changed to 3.1415926, you can only modify them one by one without the macro definition. But with the macro definition, you only need to modify the macro definition:
#define PI 3.1415926
It can be seen that each # define command consists of three parts: # define command itself; abbreviations (macros); Replace text or subject. Each part is separated by spaces. Therefore, the macro name cannot contain spaces and must follow the C variable naming rules. Macro names generally use uppercase letters.
In preprocessing, the process from macro to subject becomes macro expansion. Some macro-defined subjects are relatively long. You can use the Backslash "\" at the end of a row to extend the remaining parts to the next line (but note that if the second row is not left aligned, the white spaces at the beginning will also be considered as part of the subject ).
The entity part can be a constant, a C expression, or even a complete statement (with a semicolon). In short, it can be any string. Note that if the main body still contains a macro name, the macro will be replaced. However, if the macro name is enclosed in double quotation marks, then there will be no macro replacement, but it will be understood literally.
(2) class function macros
Macro definition is divided into two types. The macro mentioned above is called a Class Object macro without parameters, which is also called a symbolic constant. Another type of macro with parameters is called a class FUNCTION macro. For example:
#define FUN(X) X * X
The shape of a class FUNCTION macro is very similar to that of a function. It is followed by a pair of parentheses and the parameter list is placed in parentheses. Then the subject is an operational rule for these parameters. When this macro is used, X can be replaced by other characters, that is, the function parameters are the same, and X serves as a parameter.
Code like this:
x = FUN(4);
Will be replaced:
x= 4 * 4;
It may be a bit difficult, but I personally divided the macro development process into two steps: first, replace FUN (4) with X * X; then Replace "real parameter" 4 with "shape parameter" X (I don't know if the machine is doing this, will it be an even innovation ?).
But be cautious with class function macros: When the Preprocessor expands the macro, it only performs the text replacement operation, rather than the function passing parameters. For example, the macro used just now:
x = FUN(3 + 4);
We expect to replace it:
x = 7 * 7;
Actually:
x = 3 + 4 * 3 + 4;
We will not get the desired result because of the combination of order. To avoid such a result, we recommend that you add brackets to each parameter that appears in the subject when defining a class FUNCTION macro, and also protect each operation rule with parentheses. For example, FUN should be defined as follows:
#define FUN(X) ((X) * (X))
The replacement is like this:
x = ((3 + 4) * (3 + 4))
This seems troublesome, but it is a good way to avoid accidents.
The following is the handling time (people write too well, so I am so cool to steal it ~, From Linux C one-stop programming)
FUNCTION macro definitions are often written in this form (from kernel code include/linux/pm. h): # define device_init_wakeup (dev, val) \ do {\ device_can_wakeup (dev) = !! (Val); \ device_set_wakeup_enable (dev, val); \} while (0) Why should I use do {...} while (0) to enclose it? What is the problem? # Define device_init_wakeup (dev, val) \ device_can_wakeup (dev) = !! (Val); \ device_set_wakeup_enable (dev, val); if (n> 0) device_init_wakeup (d, v); after the macro is expanded, the second statement of the function body is not in the if condition. Can I simply use {...} to enclose it as a statement block? # Define device_init_wakeup (dev, val) \ {device_can_wakeup (dev) = !! (Val); \ device_set_wakeup_enable (dev, val);} if (n> 0) device_init_wakeup (d, v); else
Continue; the problem lies in the number at the end of device_init_wakeup (d, v);. If this number is not allowed, it does not look like a function call. If this number is written, after the macro is expanded, a syntax error occurs. if the if statement is ended with the if sign, it cannot be paired with else. Therefore, do {...} while (0) is a better solution.
Then I want to add, how does the form do {...} while (0) run? We know that such do... A while () loop is called an exit condition loop. When a condition is checked after the loop is executed, the statement in the loop body can be executed at least once, in addition, the while condition is set to 0, that is, the loop body is executed only once. This is a clever way !!
(3) # And # Operators
It's really a bit difficult to write it here. Mei's C language is really profound and profound. A macro definition must be so complicated...
As mentioned above, the macro name in double quotation marks in the subject will not be replaced but will be treated as normal text. What if we need to replace it? (Why is there such a demand ?) The method is to add a # symbol before the macro name. The term is stringizing ).
Note: This symbol is only used for parameters in the class FUNCTION macro, that is, this usage in the Class Object macro does not work (I tried it, it is true ).
# The operator combines two language symbols into a single language symbol, but it can also be used to replace the Class Object macro, called the binder of The Preprocessor. In my opinion, it is used to name objects (variables or functions). For example, we often name variables like x1 x2 x3, the features of such names remain unchanged while others change. Chestnuts:
#define XNAME(n) x ## n
Then
int XNAME (1) = 14;
Will be replaced:
int x1 = 14:
The whole article is complete.