In the C and C + + languages, an identifier is allowed to represent a string, called a macro, which can be a constant, an expression, a format string, and so on. When compiling preprocessing, all occurrences of the "macro name" in the program are substituted with the string in the macro definition, which is called "macro substitution" or "macro expansion". A macro definition is done by a macro definition command in the source program. Macro substitution is done automatically by the preprocessor. If the string is an expression, we call it a functional macro definition, what is the difference between a function-type macro definition and a normal function? Let's take the following two lines of code, for example, to expand the description:
Functional macro Definition: #define MAX (A, B) ((a) > A):(B))
normal function: MAX (A, b) {return a>b?a:b;}
(1) Function-type macro-defined parameters do not have a type, the preprocessor is only responsible for the formal substitution, and do not do parameter type checking, so you should take extra care when you pass the parameter.
(2) The code that calls the real function and the code that calls the function-style macro definition generate different instructions.
If Max is a normal function, then its function body return a > B? A:B; To compile the build instructions, each call that appears in the code is also compiled to generate the pass-through directive and the invoke command. And if Max is a functional macro definition, the macro definition itself does not have to compile the build instructions, but every call to compile generated instructions in the code is equivalent to a function body, rather than a simple number of pass-through instructions and calls instructions. Therefore, using a function-style macro to define the generated target file for compilation is larger.
(3) The function-type macro definition should pay attention to the format, especially the parentheses.
If the function-type macro definition above is written as #define MAX (A, B) (A>B?A:B) and the inner brackets are omitted, then the macro expansion becomes k = (i&0x0f>j&0x0f?i&0x0f:j&0x0f), The priority of the operation is wrong. Similarly, the outer brackets of this macro definition cannot be saved. If a macro is replaced with ++max (A, B) in the function, the macro expands to + + (a) > (b)? (a):(B), the arithmetic priority is also wrong.
(4) If the function argument is an expression, then the call to the normal function is not the same as the replacement procedure for the function-type macro definition.
The value of the actual argument expression is passed to the formal parameter before the normal function call, if the argument expression has side Effect, then these sideeffect only occur once. For example Max (++a, ++b), if Max is a normal function, A and B are incremented only once. But if the MAX function-type macro is defined, then expand to K = ((++a) > (++b)? ( ++A):(++b), A and B are not necessarily added once or twice. So if the argument is an expression, replace the function-type macro definition with a careful look.
(5) Functional macro definitions tend to result in lower code execution efficiency.
Look at the following section of code:
int a[]={9,3,5,2,1,0,8,7,6,4};
int Max (n)
{
Return N==0?a[0]:max (A[n],max (n-1));
}
int main ()
{
Max (9);
return 0;
}
In the case of a normal function, the time complexity is O (n) by recursion, the desired maximum value. But in the case of a functional macro definition, the macro expands to (A[n]>max (n-1), A[n]:max (n-1)), where Max (n-1) is called two times, so that recursion goes on and the time complexity is high.
Although there are many drawbacks to functional macro definitions compared to normal functions, it is possible to significantly improve the execution efficiency of the code by careful use, which eliminates the need to allocate and release stack frames, pass parameters, return values, and so on, so those short and frequently called functions are often replaced with functional macro definitions.
C + + Journal macro definition function