First, #define的基本用法
#define是C语言中提供的宏定义命令, the main purpose is to provide programmers with certain convenience in programming, and to a certain extent, improve the efficiency of the program, but students often do not understand the nature of the command in learning, always create some confusion here, in the programming of the misuse of the command, To make the program run inconsistent with the intended purpose, or to read the program written by others, the results of the operation to understand the error, which is bad for C language learning.
1 #define命令剖析
1.1 #define的概念
#define命令是C语言中的一个宏定义命令, which is used to define an identifier as a string, which is called the macro name, and the defined string is called the replacement text.
the command has two formats: one is a simple macro definition and the other is a macro definition with parameters.
(1) Simple macro definition:
- #define < Macro name > < string >
- Example: #define PI 3.1415926
(2) macro definition with parameters
- #define < Macro name > (< parameter table >) < macro body >
- Example: #define A (x) x
When an identifier is defined by a macro, the identifier is a macro name. In this case, the macro name appears in the program, and before the program is compiled, the macro name is replaced with the defined string, which is called the macro substitution, which is not compiled until it is replaced.macro substitution is a simple replacement。
1.2 Macro Replacement When the time comes
In order to really understand the role of # define, let's look at the process of C language source program. When we compile a well-written source program in an integrated development environment such as Turbo C, we actually undergo several processes of preprocessing, compiling, assembling, and connecting. Where the preprocessor produces the output of the compiler, it implements the following functions:
(1)file contains
You can extend the # include in the source program to the body of the file, i.e. locate and expand the contained. h file to the location of # include.
(2) Conditional compilation
The preprocessor includes a part of the source program in or out of the compilation commands, such as # if and #ifdef, and usually converts the excluded statement to a blank line.
(3) Macro expansion
The preprocessor expands the macro reference that appears in the source program file into the corresponding macro definition, which is what this article describes as the function of # define, which is done by the preprocessor.
The source program processed by the preprocessor differs from the previous source program, where the work performed is purely a substitution and unwinding, without any computational function, so as long as you can really understand this when learning the # define command, it will not cause misunderstanding and misuse of this command.
2 #define使用中的常见问题解析
2.1 Simple macros define problems that occur in use
In the use of simple macro definitions, it is easy to misunderstand and misuse when the replacement text represents a string that is an expression. The following example:
- Example 1 #define N
- void Main ()
- {
- int a=n*n;
- printf ("%d", a);
- }
(1) problems occurred:In this program, there is a macro definition command, macro n represents the string is the use of macro n in the program, the general students in reading the program, the problem is prone to solve N is 2+2=4, and then in the program to calculate a when using multiplication, that is, n*n=4*4=16,in fact, the result of the problem is 8, why the result has such a large deviation?
(2) Problem analysis:As described in section 1,macro expansion is done in the preprocessing phase, this phase of the replacement text just as a string, and there will be no computation, at the time of the expansion of macro n is simply the use of the string to replace N, do not add any symbols, so the result of the program expansion is a=2+2*2+2, after the calculation = 8, which is the essence of macro substitution, how to write a program to complete the result of 16 of the operation?
(3) Workaround:
- /* Write the macro definition as follows */
- #define N (+)
- /* This can be replaced by (* * *) * (=16*/)
2.2 Problems with the macro definition with parameters
In the use of macro definitions with parameters, it is very easy to cause misunderstanding. For example, we need to make a macro substitution to find the square of any number, which requires the use of parameters to replace the parameters in the macro definition with actual parameters in the program. General students are easily written in the following form:
- #define AREA (x) x*x
- /* This is very easy to use in the problem, see the following program */
- void Main ()
- {
- int y = Area (+ +);
- printf ("%d", y);
- }
Supposedly given the parameter is the 4*4=16, the resulting result should be a, but wrong, because the actual result of the program is 8, is still not able to follow the pure simple substitution rules, but also the first calculation and replacement,in this procedure, the 2+2*2+2=8 is the parameter in the area macro, which should be replaced by the x in the macro definition. What if we follow the solution in (1) and enclose it in the X-ray of the macro body? #define AREA (x) (x) * (x), for area (+/-a), with (+/-() * (+) * (+) = 16, can be resolved,but what about the area (/area )?Some students see this problem immediately give results, because the numerator denominator, again wrong, or forget to follow the first substitution of the rules, this problem will change to (* * +) * (* * +)/(* * * * * * () * (4*4/4*4) * (* * * * * * * * * * * * * * * * * * * * 16, what should it be? The workaround is to add a parenthesis to the entire macro body, i.e.#define AREA (x) ((x) * (x)), don't think it's unnecessary, without it, it can't be.
To be able to really use a good macro definition, when you read someone else's program,It is important to remember to first replace the use of macros in the program with the string it represents, do not take the liberty to add any other symbols, fully expanded after the corresponding calculation, will not write wrong running results. If you are programming with macro substitution, when using a simple macro definition, when there is more than one symbol in the string, the parentheses show precedence, and if it is a macro definition with parameters, enclose each parameter in the macro body with parentheses over the entire macro body. See here, can't help but ask, with macro definition so troublesome, so error-prone, can abandon it, let us look at the C language with the benefits of macro definition. Such as:
- #include <iostream.h>
- #define PRODUCT (x) x*x
- int main ()
- {
- int i=3;
- int j,k;
- j = Product (i++);
- cout<< "j=" <<j<<endl;
- cout<< "i=" <<i<<endl;
- K = Product (++i);
- cout<< "k=" <<k<<endl;
- cout<< "i=" <<i<<endl;
- return 0;
- }
output results in turn:j=9;i=5;k=49;i=7
3 Benefits of macro definition
(1) Modification of the convenience program
Using simple macros to define available macros instead of a constant used in the program, so that when the constant changes, not the whole program to modify, only the macro definition of the string can be, and when the constant is longer, we can use a shorter meaningful identifier to write the program, which is more convenient. What we call a constant change is not a change in the course of a program, but a modification during programming, a familiar example of which Pi Pi is a commonly used value in mathematics, Sometimes we will use 3.14来 to say, sometimes also use 3.1415926, which depends on the accuracy of the calculation, if we are programmed to use it multiple times, then we need to determine a value, in this operation does not change, but perhaps later found that the application of the accuracy of the performance changes, need to change its value, This needs to modify all the relevant values in the program, which will bring us some inconvenience, but if you use a macro definition, using an identifier instead, then modify only the macro definition, you can also reduce the input 3.1415926 such a long number of times the case, we can define #define PI 3.1415926, both reduce the input and easy to modify, why not?
(2) Improve the operation efficiency of the program
Use a macro with parameters to define functions that can accomplish function calls, and to reduceSystem overhead to improve operational efficiency. As mentioned in the C language, the use of functions can make the program more modular, easy to organize, and reusable, but in the event of a function call, you need to retain the calling function of the field, so that the completion of the execution of the child function can return to continue execution, as well as the child function after the completion of the call function to restore the scene, If the child function performs more operations, this conversion time overhead can be ignored, but if the function of the child function is relatively small, or even a single point of operation, such as the operation of a multiplication statement, this part of the conversion cost is relatively large, but the use of parameters with the macro definition will not occur this problem, Because it is a macro expansion during the preprocessing phase, it does not need to be converted at execution time, which is executed locally. A macro definition can do simple things, but a complex operation is still done by a function call, and the macro definition occupies a relatively large target code space. So when you use it, you decide whether to use a macro definition, depending on the situation.
4 Conclusion
This paper analyzes the problem that the macro definition # # is easy to appear in the C language, and analyses the processing of # define from the point of view of C source program processing, and expounds its merits. As long as you can understand the rules of macro expansion, master the use of macro definition, is in the preprocessing phase of the source program to replace, just use the corresponding string to replace the macro name appearing in the program, so that the correct use on the basis of the full enjoyment of the use of macro definition to bring convenience and efficiency
Ii. three special symbols in define: #,##,#@
- #define CONN (x, y) x# #y
- #define TOCHAR (x) #@x
- #define TOSTRING (x) #x
(1)what doesx# #y mean? Represents x connection Y, for example:
- int n = Conn (123,456); /* Results are n=123456;*/
- char* str = Conn ("asdf", "ADF"); /* The result is str = "ASDFADF"; */
(2) Look again
#@x
is to add a single quotation mark to x, and the result is a const char. For example,
char a = ToChar (1); The result is a= ' 1 ';
Do a cross-border test. Char a = ToChar (123); the result is wrong;
But if your parameter exceeds four characters, the compiler will give you an error! Error C2015:too many characters in Constant:p
(3) Finally, look at #x, you know, he's giving X double quotes.
char* str = ToString (123132); str= "123132";
third, some common macro definitions
1 Prevent a header file from being repeatedly contained
- #ifndef Bodydef_h
- #define Bodydef_h
- Header file Contents
- #endif
2 Gets a byte or a word on the specified address
- #define MEM_B (x) (* (BYTE *) (x))
- #define MEM_W (x) (* ((Word *) (x)))
Use the following:
- #include <iostream>
- #include <windows.h>
- #define MEM_B (x) (* ((byte*) (x)))
- #define MEM_W (x) (* ((word*) (x)))
- int main ()
- {
- int btest = 0x123456;
- byte M = Mem_b ((&btest));/*m=0x56*/
- int n = mem_w ((&btest));/*n=0x3456*/
- return 0;
- }
3 Get the offset of a field in the struct (struct)
- #define OFFSETOF(Type, field) ((size_t) & ((type *) 0), field)
Please refer to the article: detailed
write macro definition: Gets the offset of a field in the struct type .
4 Gets the number of bytes occupied by the field in a struct
- #define FSIZ (type, field) sizeof (((type *) 0)->field)
5 Get the address of a variable (word width)
- #define B_PTR (Var) ((BYTE *) (void *) & (Var))
- #define W_PTR (Var) ((Word *) (void *) & (Var))
6 Convert one letter to uppercase
- #define UPCASE (c) (((c) >= ' A ' && (c) <= ' Z ')? ((c)-0x20): (c))
7 A number that determines whether a character is a 10-in value
- #define DECCHK (c) ((c) >= "0" && (c) <= ' 9 ")
8 A number that determines whether a character is a 16-in value
- #define HEXCHK (c) (((c) >= ' 0 ' && (c) <= ' 9 ") | | (c) >= ' A ' && (c) <= ' F ') | | ((c) >= ' A ' && (c) <= ' F '))
9 One way to prevent overflow
- #define INC_SAT (val) (val = (val) +1 > (val))? (val) +1: (val))
10 Returns the number of array elements
- #define ARR_SIZE (a) (sizeof ((a))/sizeof ((a[0)))
11 Debugging with some macro tracking
The ANSI standard describes five predefined macro names. They are:
- _line_/* (two underscore), corresponding to%d*/
- _file_/* Corresponds to%s*/
- _date_/* Corresponds to%s*/
- _time_/* Corresponds to%s*/
A detailed description of C + + macros