C language - macro (turn: https: //blog.csdn.net/hairetz/article/details/4785047)

Many C ++ books advise us macro C language is first of all evil, but things always as good as we thought it would be bad, just as goto same. Acer has
a large role is to automatically generate the code for us. If the template can produce a variety of other type of code (type do not replace) for us,
then the macro can actually generate new code (ie symbol substitution, increase) on the symbol for us.

About some of the syntax of the macro issues, can be found on google. Believe me, you so much for absolutely no understanding of the macro you think. If you
do not know and # ##, do not know prescan, then you must understand the macro is not enough.

I was a little explain some grammatical problems at the macro (say grammar problem seems to be wrong, macro preprocessor and only about, but nothing to do with the semantic analysis):

1. The macro can be defined like a function, for example:
#define min (the X-, the y-) (the X-but in actual use, only when the write min (), must be added in parentheses, min will be expanded as a macro, or not do any processing.

2. If the macro requires parameters, you can not pass, the compiler will give you a warning (macro arguments is not enough), but this will result in an error. Such as C ++ books as described
above, the compiler (preprocessor) macro syntax checking is not enough, so the more you have to check the work for themselves.

3. many programmers do not know # ## and
# symbols put directly into a symbol string, for example:
#define STRING (X) #x is
const char * str = STRING (test_string); str content is "test_string" , that will followed by # sign
directly in double quotation marks.
## will be connected to two symbolic symbols, thereby generating a new symbol (lexical hierarchy), for example:
#define the SIGN (X) X ## _ the INT
int the SIGN (. 1); macro is expanded will be: int INT_1;

4. macro varying parameter, the relatively cool, so that you can define similar macros:
#define the LOG (the format, ...) the printf (the format, __VA_ARGS__ in)
the LOG ( "% S% D", STR, COUNT);
__VA_ARGS_ _ is a predefined macro system, the parameter list is automatically replaced.

5. When a macro calls itself, what happens? For example:
#define the TEST (the X-) (the X-+ the TEST (the X-))
the TEST (1); What happens? In order to prevent unlimited expansion recursive, grammar provides that when a macro meet her, stop start, that is
to say, when the TEST (1) be expanded, expand the process discovered a TEST, then this will TEST as a general symbol. TEST (1)
was eventually expanded to: 1 + TEST (1).

Prescan 6. macro parameters,
when macro parameters are put into a macro body, the macro is expanded all first parameter (exceptions, see below). When the macro parameters are put into a macro body expansion,
the preprocessor new expanded macro body is second scanning, and continues to expand. For example:
#define PARAM (X) X
#define addParam (X) X ## _ the INT
PARAM (ADDPARAM (1));
as ADDPARAM (1) as a parameter PARAM of the macro, so the first ADDPARAM (1) is expanded INT_1, then INT_1 into PARAM.

The exception is if the PARAM macros using # ## or the macro parameters, then the macro parameters will not be expanded:
#define PARAM (the X-) #x
#define addParam (the X-) ## INT _ the X-
PARAM (addParam (1) ); it will be expanded to "aDDPARAM (1)".

The use of such a rule, you can create a very interesting technology: print out of the way after a macro is expanded, so you can easily analyze the code:
#define to_string (the X-) TO_STRING1 (the X-)
#define TO_STRING1 (the X-) #x
to_string first x will all unfold (if x is a macro words) and then pass TO_STRING1 converted to a string, now you can do:
const char * str = to_string (PARAM (addParam (1))); to explore expansion PARAM look after.

7. A very important addition: Like I said in the first point above, if a function does not appear like macro brackets in use, then the preprocessor just
this macro as a general symbol processing (processing that is not ).


Let's experience how the macro is to help us automatically generate code. As I said, the macro code that is generated in the symbol level. I analyze Boost.Function
time module, because it uses a lot of macros (macro nesting, nest again), cause I did not even understand the code. Later I found a small template library ttl, said
that the development of a number of small components to replace part of the Boost (which is a good reason, because Boost does too). Similarly, the library also contains a function library.
Here is the function I mentioned before functor. ttl.function Curry To automatically generate a lot of similar code, use a macro:

TTL_FUNC_BUILD_FUNCTOR_CALLER #define (n-) /
Template <R & lt typename, TTL_TPARAMS (n-)> /
struct functor_caller_base n-## /
/// ...
ultimate aim of the macro is: by calling similar manner TTL_FUNC_BUILD_FUNCTOR_CALLER (1) automatically produce many functor_caller_base template:
template struct functor_caller_base1
template struct functor_caller_base2
template struct functor_caller_base3
/// ...
then, the core part wherein TTL_TPARAMS (n) this macro can be seen that this macro is ultimately produced:
typename Tl
typename Tl, T2 typename
typename Tl , typename T2, T3 typename
/// ...
Let us analyze the process TTL_TPARAMS (n) a. The main macro analysis to grasp some of the points I mentioned above. The following procedure I suggest that you turned over the ttl code
associated code files: function.hpp, macro_params.hpp, macro_repeat.hpp, macro_misc.hpp , macro_counter.hpp.

so, here we go

Analysis, drill down, drill down, for example TTL_TPARAMS (1):

TTL_TPARAMS #define (n-) TTL_TPARAMSX (n-, T)
=> TTL_TPARAMSX (. 1, T)
#define TTL_TPARAMSX (n-, T) TTL_REPEAT (n-, TTL_TPARAM, TTL_TPARAM_END, T)
=> TTL_REPEAT (. 1, TTL_TPARAM, TTL_TPARAM_END, T)
TTL_TPARAM #define (n-, T) n-typename T ##,
#define TTL_TPARAM_END (n-, T) T ## n-typename
#define TTL_REPEAT (n-, m, L, P) TTL_APPEND (TTL_REPEAT_, TTL_DEC (n-)) (m , l, p) TTL_APPEND (TTL_LAST_REPEAT_ , n) (l, p)
note, TTL_TPARAM, TTL_TPARAM_END although it has also two macros, they are as an argument TTL_REPEAT macro, in accordance with the rules prescan, seems to be first
of these two re-transmission of macro expansion to TTL_REPEAT. But, as I highlighted earlier, these two macros are function-like macro, need to use parentheses,
if not bracketed, not as a macro processing. Thus, when expanded TTL_REPEAT, it should be:
=> TTL_APPEND (TTL_REPEAT_, TTL_DEC (. 1)) (TTL_TPARAM, TTL_TPARAM_END, T) TTL_APPEND (TTL_LAST_REPEAT_,. 1) (
TTL_TPARAM_END, T)
The macro body seem complex, under a careful analysis, can be divided into two parts:
TTL_APPEND (TTL_REPEAT_, TTL_DEC (. 1)) (TTL_TPARAM, TTL_TPARAM_END, T) and
TTL_APPEND (TTL_LAST_REPEAT_, 1) (TTL_TPARAM_END , T)
to the first portion Analysis :
#define TTL_APPEND (x, y) TTL_APPEND1 (x, y) to expand // x, y and then x, y connected
#define TTL_APPEND1 (x, y) X ## Y
#define TTL_DEC (n-) TTL_APPEND (TTL_CNTDEC_ , n)
on a first-deployment parameters, will first expand TTL_DEC (. 1)
=> TTL_APPEND (TTL_CNTDEC_,. 1) => TTL_CNTDEC_1
#define TTL_CNTDEC_1 0 Note, TTL_CNTDEC_ not a macro, TTL_CNTDEC_1 is a macro.
=> 0, that is, TTL_DEC (1) eventually expands to 0. Back part TTL_APPEND:
=> TTL_REPEAT_0 (TTL_TPARAM, TTL_TPARAM_END, T)
#define TTL_REPEAT_0 (m, L, P)
TTL_REPEAT_0 This macro is empty, then the above said first portion is ignored, now only the second part:
TTL_APPEND (TTL_LAST_REPEAT_, 1) (TTL_TPARAM_END, T)
=> TTL_LAST_REPEAT_1 (TTL_TPARAM_END, T) // TTL_APPEND 1 and merge the TTL_LAST_REPEAT_
#define TTL_LAST_REPEAT_1 (m, P) m (1, P)
=> TTL_TPARAM_END (1, T)
#define TTL_TPARAM_END (n-, T) T typename n-##
=> Tl typename expand completed.
---------------------
Author: cat has been brought back
Source: CSDN
Original: https: //blog.csdn.net/hairetz/article/details/ 4785047
Disclaimer: This article is a blogger original article, reproduced, please attach Bowen link!

Guess you like

Origin www.cnblogs.com/ptfe/p/11222977.html