(i) Symbolic constants
A macro definition is a substitution policy in C that uses a preprocessing command #define equate a string of (verbose) text with a name (called a macro), and then you can use the macro in bulk in the source code. In the preprocessing phase, replace the macros in the source code with the original text. For example, in the source code:
#define PI 3.14
Then in the next code, you need to write 3.14 of the place can be directly replaced by PI. When the pretreatment, pi all changed back to 3.14.
What's the benefit of this exchange? In case the 3.14 of the code needs to be changed to 3.1415926, then if you don't have the macro definition, you can only modify it, but with the macro definition, just modify the macro definition:
#define PI 3.1415926
As you can see, each #define command consists of three parts: #define命令本身, abbreviation (macro), or replace text or body. Each part is separated by a space, so a space cannot exist in the macro name and must follow the C variable naming convention. Macro names generally use uppercase letters.
In preprocessing, the process of changing from macro back to body becomes macro expansion. Some macros define a body that is long, and you can use the backslash "\" at the end of the line to extend the remainder to the next row (but note that if the second line is not left aligned, the opening whitespace will also be treated as part of the body).
The body part can be a constant, a C expression, or even a complete statement (that is, with a semicolon), and can be any string. Note that if the body still contains the macro name, the macro will also be replaced, but if the macro name is enclosed in double quotes in the body, then the macro substitution will not occur and is understood literally.
(b) Class function macros
There are two types of macro definitions, all of which are without parameters, called Class object macros, which are also called symbolic constants, and a parameter called a class function macro. For example:
#define FUN (x) x * x
The shape of a class function macro is similar to a function, followed by a pair of parentheses after the name, and then the argument list is placed in parentheses. Then the subject is some sort of operation rule for these parameters. When using this macro, X can be replaced by other characters, just like the parameters of the function, X plays the role of the parameter.
Code in code such as:
x = FUN (4);
will be replaced by:
x= 4 * 4;
Maybe a little bit around, but I personally put this macro-expansion process into two-step understanding: First, replace the fun (4) directly into X * x, and then use the "argument" 4 instead of "formal parameter" X (not know whether the machine is doing this, will not be a couple of innovation.) )。
But be wary of class-function macros: The preprocessor does only text substitution when the macro is expanded, not as a function argument. For example, the macro used just like this:
x = FUN (3 + 4);
We would expect to replace it with:
x = 7 * 7;
Can actually be:
x = 3 + 4 * 3 + 4;
We don't get the results we want because of the combination sequence. The way to avoid this is that when you define a class function macro, it is a good idea to enclose each argument that appears in the body with parentheses, and also to protect each operation rule with parentheses. For example, fun should define this:
#define FUN (x) ((x) * (x))
So that's what happens when you replace it:
x = ((3 + 4) * (3 + 4))
This may seem like a hassle, but it's a good way to avoid surprises.
The following is the handling time (people write too wonderful, I would be ashamed to steal lazy ~, excerpted from the "Linux C one-stop programming")
Functional macro definitions are often written in this form (taken 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 do you want to surround it with do {...} while (0)? What's the problem without enclosing it
? #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 this macro expands, the second statement of the function body is not in the IF condition. Then simply use {...} to form a
sentence 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 is device_init_wakeup (d, v); At the end of; Number, if not allowed to write this; Number, it does not look like a function call, but if you write this; , if the macro is expanded, there is a syntax error, if the statement is this; The number is over and cannot be
paired with else. Therefore, do {...} while (0) is a better solution.
Then I'll add, do {...} while (0) exactly how this form works. As we know, this do...while () loop is called an exit condition loop, and the judgment condition is checked after the loop is executed, which guarantees that the statement in the loop body is executed at least once, and that the while condition here is set to 0, which means that the loop body just executes once, which is really smart.
(iii) #与 # #运算符
Write here really a little hold up, Sister's C language is really profound, a macro definition to make so complex ...
As mentioned above, the macro name within the double quotation marks in the body is not replaced but is treated as plain text, so if it has to be replaced. (Say how there is two of demand.) method is to precede the macro name with a # symbol, the term is called: stringizing.
Note: This symbol is only used in the parameters of the class function macro, that is, the usage in the Class object macro doesn't work (I tried, it's true).
# #运算符把两个语言符号组合成单个语言符号, but it can also be used for the replacement of class object macros, known as preprocessor binders. In my opinion, it is used to name the object (variable or function), such as we often give the variable x1 x2 x3 Such names, the characteristics of such names are part of the same and the other part of the change. Chestnuts:
#define XNAME (n) x # # N
And then
int XName (1) = 14;
will be replaced by:
int x1 = 14:
On the sauce, finished.