Address: http://hi.baidu.com/bellgrade/blog/item/391c1b2b8cd932325343c1b9.html
Let's start with a relatively simple example.
View plainprint?
- # define f (a, B) a ## B
- # define g (a) # A
- # define H (a) g (a)
- H (f ( 1 , 2 )
- G (f (1,2))
I believe many people have seen this example. Let's take a closer look at its parsing process. It should be like this:
For G (f (1, 2), the Preprocessor first sees G, then (, indicating that this is a functional macro, well, and then replaces the real parameter F (1, 2), and obtain # F () (Note: This is invalid because it is used for convenience #, so the next step will not replace the F parameter! Therefore, the resolution is completed after "F (1, 2)" is obtained. For H (f (), The Preprocessor first sees h, and then (, replaces its parameter F (1, 2, get g (f (). Note that the next step here is that the pre-processor will continue to go back and process the obtained F () instead of going back and then processing G! Get 12. Here we get a: G (12), rescan the entire macro, replace g, and finally get 12 ".
The description in section 6.10.3.1 of the standard is still clear, and it writes as follows:
after the arguments for the invocation of a function-like macro have been
identified, argument substitution takes place. A parameter in the replacement
list, unless preceded by a # Or # preprocessing token or followed by a ##
preprocessing token (see below), is replaced by the corresponding argument
after all macros contained therein have been expanded.
Note the bold part. Here, we can briefly summarize the basic replacement process of function macros:
First, we need to identify that this is a functional macro. Through what? Shown in the call (, yes, it's a left brace! Here, the next step is to replace the parameters, that is, to replace all the real parameters according to the macro definition, and then go backward, unless we encounter # And # (as G in the above example), we can replace or expand the macro if it is still known in the replacement, until the parsing ends: All parameters have been replaced (or # Or # has been processed); finally, the Preprocessor will scan the entire macro again, because some new things may be replaced in the previous round (such as H in the above example ).
At this point, there are no problems. In fact, there are many problems! Why? Because macro replacement can not only occur when a macro is called, but also when it is defined!
Question 1: will the macro name be replaced?
You can also ask this question: Can macros be redefined? Not allowed, but the same redefinition is allowed. The standard reads:
An identifier currently defined as an object-like macro shall not be
Redefined by another # define preprocessing directive unless the second definition
Is an object-like macro definition and the two replacement lists are identical.
Likewise, an identifier currently defined as a function-like macro shall not be
Redefined by another # define preprocessing directive unless the second definition
Is a function-like macro definition that has the same number and spelling
Parameters, and the two replacement lists are identical.
Question 2: Will macro parameters (parameters) be replaced?
Here is an example to illustrate this problem:
# Define Foo 1
# Define bar (FOO) Foo + 2
Bar ()
Do we get a + 2 or 1 + 2? A + 2! Because the parameters will not be replaced, you can think about it. If the parameters are replaced with this macro, it will be useless! What about real parameters? Yes, because the replacement of the real parameter takes place before the parameter is passed:
Before being substituted, each argument's preprocessing tokens are
Completely macro replaced as if they formed the rest of the preprocessing File
Question 3: Will symbols other than macro parameters be replaced?
Yes, the above mentioned "after all macros contained therein have been expanded", that is, this occurs before the parameter is replaced. However, there is a very strange question: What if the replaced symbol is exactly the same as the shape parameter? As in the following example:
# Define Foo bar
# Define Baz (bar) BAR + foo
Baz (1)
Will we get 1 + 1 or 1 + bar? The latter, because the replaced bar is not included in the parameter, although the standard does not clarify this. Think about it. If so, the macro definition will also be broken!
Another example:
# Define Foo bar
# Define MAC (x) x (FOO)
MAC (FOO)
According to the above, we first get Foo (FOO), then foo is replaced with bar, and finally get Bar (bar ).
Now, we can look at more complex examples:
# Define M! (M) + n
# Define n (n) n (m)
M (m)
This example is quite complex and is the most complex macro I have ever seen. :-) We may be a bit blind at the moment. It doesn't matter. Let's come one step at a time.
The first step is good. The first M is replaced directly and the result is :! (M) + n (m), don't hesitate, go down, replace the last m, and get :! (M) + N (! (M) + n), then this scan has been completed. Here we have to propose another thing to continue, you may know, recursion. The standard description is as follows:
if the name of the macro being replaced is found during this scan of the
replacement list (not including the rest of the source file's preprocessing
tokens), it is not replaced.
In the last replacement, M is replaced, so mHereWill not be replaced, so the next step is to replace the first N, and get :! (M) +! (M) + n (m). Note that anotherNewM, this m will be replaced, because this scan is not completed! In the next step, get :! (M) +! (M) + N (! (M) + n). After the second scan is completed, all the replications are completed.
In summary, we can sum up two important macro replacement rules: 1) a complicated macro is only scanned twice, and recursion is not allowed, even at 2nd times; 2) After replacement, if scanning is not completed, continue from the replaced one.
End