C macro definition usage analysis

  • 2020-04-01 21:29:38
  • OfStack

1. How to distinguish "macro name" from "macro string" in macro definition? What should be noticed about macros with arguments?

In a macro definition, "macro name" and "macro string" are distinguished by "space". When the compiler processes the macro definition, it first reads the string from the first space after "#define" until it meets the next space. The string between the two Spaces is "macro name". After the "macro name" is determined, all other strings on the line are "macro strings". Figure: #define + N Spaces (1 < N) + macro name (no Spaces) + N Spaces (1 < N) + macro string (until end of line). The macro definitions covered here are all within a line, and if they span multiple lines they are "extended" with the "\" character, which is essentially treated like a line.

For parameterized macros, there must be no space between the name of the macro and "()", otherwise it becomes "parameterless macros" (according to the above principle). And when "parameterless macros" and "parameterized macros" have the same name, "parameterless macros" will mask "parameterized macros", even if called in the "parameterized macros" way, will not work.

Test contents and results :

< img Alt = "" border = 0 SRC =" / / files.jb51.net/file_images/article/201212/201212050858077.jpg "> < img Alt =" "border = 0 SRC =" / / files.jb51.net/file_images/article/201212/201212050858078.jpg ">

Experimental analysis :

You can see the "#define PI & recipe; 3.1415 "and" #define PI 689 "are two different macro definitions" PI "and" P "respectively; G of 4 "is replaced by (X) (2 X) (4); When "F(4)" is called, the system is not replaced with "2*4", but with "123(4)", saying "#define F & cake; 123 "completely off the #define F(X) & cake; (2*X) ", when the "#define & award"; F   123 "after "#define F(X) & cake; (2*X)" works fine. Therefore, pay close attention to the effect of whitespace when defining macros, and the names of "parameterized macros" and "parameterless macros" must not be the same, otherwise confusion will occur. However, whitespace does not affect the effect when a macro is called, for example, F(3) and F(3) are the same (F(X) is a macro with arguments).

2. How do macros and functions differ in usage and effect?

When macros are defined, we should be good at using parentheses to encapsulate variables and enclose each parameter to prevent problems related to priority. The entire resulting expression should also be enclosed to prevent problems when the macro is used for a more complex expression. Maximize the reliability of macros. For example: "#define ABS(x) & recipe; (((x) > 0)? (x) : (-x)) is far more reliable than #define ABS(x) & recipe; X > 0? X: -x ", ABS(a-b) can be used for the test.

If you have a self-increment (++) or self-decrement (--) operator when making a macro call, be sure to be aware of the potential for side effects. Because the macro in the substitution, if the variable appears many times, it is equivalent to self - add or self - subtract operation into many times, this is completely different from the function call, the function call will copy the value of the argument, and the parameter operation will not affect the argument, and the macro call is directly modify the argument many times. For example: a = 5; "ABS(a++) "becomes" (((a++) > 0)? (a++) : (-a++)) ", after the operation is completed, "a = 7" instead of "a = 6"; You don't have to worry about that at all when you write it as a function.

If multiple nested calls are made during the macro invocation, the macro expansion will result in a very large and complex expression. This is not the case with function calls.

3. Distinction between macros and type defs

Since the essence of macros is substitution, variable types can be encapsulated in a single layer, which can be used to define variables. The advantage of this is increased portability, and only the macro definition needs to be changed when modified. Such as:

 
MY_TYPE a; 
MY_TYPE b,c,d; 

But it's best not to use it that way, because we have typedefs, which are type-defined. Furthermore, using type definitions makes the code more generic and avoids some of the deeper problems. Such as:
 
typedef uint_8 * MY_TYPE2 

MY_TYPE1 a,b; 
MY_TYPE2 c,d; 
Analysis of the :

Conceptually, MY_TYPE1 and MY_TYPE2 are identical Pointers to uint_8, but problems arise when we declare multiple variables. They are respectively expanded to:

 
uint_8 *a,b; 
MY_TYPE2 c,d; //Because MY_TYPE2 is already a type

As you can see, I wanted to define two pointer variables, a,b; Now it's a pointer variable a and an integer variable b, which is not what we want. MY_TYPE2 itself is a type (custom), so c and d are pointer types, as expected. Therefore, if you want to customize the type, resolutely choose "typedef" to give up the macro definition, or you will suffer.


Related articles: