Detailed definition of macro (#define)

Source: Internet
Author: User

There are many places in the C language where macro definitions are used, such as in header files to prevent header files from being repeatedly included:

#ifndef ctest_header_h
#define CTEST_HEADER_H
/header file content
#endif

Many macro definitions are also available in our common stdio.h header files, such as:

#define BUFSIZ 1024//Buffer size
#define EOF ( -1)//    table file at the end
#ifndef seek_set
#define SEEK_SET 0  // Indicates that the file pointer starts at the beginning of the file
#endif
#ifndef seek_cur
#define SEEK_CUR 1  //indicates that the file pointer starts at the current position
#endif
# ifndef seek_end
#define SEEK_END 2  //indicates that the file pointer starts at the end of the file
#endif

The process from writing the C language to generating the execution program is roughly as follows (ignoring the translation process of the compiler before preprocessing, etc.), and before the first scan (lexical scan and parsing) of the compilation, there will be preprocessing done by the preprocessor.

Preprocessing is the preprocessing part of the source program which is processed by the system reference preprocessor, and the preprocessing part refers to the preprocessing commands that start with "#", which is placed outside the function, and generally placed in front of the source file, such as: command #include, Macro command #define, etc. The reasonable use of preprocessing functions can make the program more convenient to read, modify, transplant, debug, and also conducive to modular programming. This article mainly describes the following sections of the macro definition:

1. Concept and non-parametric macros

     The simplest form of macros is the following:   replacing text #define a macro name   

Each #define line (that is, the logical row) consists of three parts: the first part is the instruction #define itself, "#" means this is a preprocessing command, "define" is a macro command. The second part is a macro (macro), generally abbreviated, its name (macro name) generally uppercase, and can not have spaces, follow the C variable command rules. "Alternate text" can be any constant, expression, string, and so on. In the preprocessing process, all occurrences of the "macro name" in your code are replaced with "replace text." This replacement process is referred to as "macro substitution" or "macro expansion" (macro expansion). "Macro substitution" is done automatically by the preprocessor. In C, "macro" is divided into two types: no parameters and parameters.

No parameter macro refers to the macro name with no parameters, the simplest macro above is no parameter macro.

#define M 5                //macro definition
#define PI 3.14            //macro definition
int a[m];                  will be replaced by: int a[5];
int b = M;                 will be replaced by: int b = 5;
printf ("PI =%.2f\n", pi); The output is: PI = 3.14

Note that the macro is not a statement and the end does not need to be added ";", otherwise it is replaced in the program, such as:

#define N;               Macro definition
int c[n];                   will be replaced by: int c[10;]; 
Error: ... main.c:133:11:expected '] '

These macros are used to represent values, so they become class object macros (Object-like macro, and class function macros, as described below).

If you want to write more than one row of macros, add a backslash at the end to allow multiple lines to connect, such as:

#define HELLO "the World
"

Note that the second line should be aligned, otherwise, such as:

#define Hello "Hello the wo\
  rld"
printf ("Hello is%s\n", hello);
The output is as follows: Hello is hello the wo  

The space between the line and the line is also used as part of the replacement text
And it can be seen from this example: if the macro name appears in the source program "", it will not be used as a macro for macro substitution.

Macros can be nested, but not in operation:

#define M 5                 //macro definition
#define mm m * m            //Macro nesting
printf ("MM =%d\n", mm);    MM is replaced by: mm = M * m, and then into mm = 5 * 5

The process of macro substitution has ended in the previous sentence, the actual 5 * 5 multiplication process is completed in the compile phase, rather than in the preprocessor session, so the macro does not operate, it simply follows the instructions to replace the text. Again, the macro for simple text replacement, regardless of the replacement text is a constant, expression or string, and so on, the preprocessor does not do any checks, if there is an error, can only be replaced by the macro after the program in the compile phase of discovery.

The macro definition must be written outside the function, and its scope is #define start, to the end of the source program. If you want to end its scope prematurely, use the #undef command, such as:

#define M 5                 //macro definition
printf ("m =%d\n", m);      The output is: M = 5
#define m               //Cancel macro definition
printf ("m =%d\n", m);      Error: ... main.c:138:24:use of undeclared identifier ' M '

You can also use macro definitions to represent data types, making your code simple:

#define STU struct Student//      macro definition STU
struct student{                 //Definition structure Student
    char *name;
    int sNo;
};
STU STU = {"Jack",};         To be replaced by: struct Student stu = {"Jack",};
printf ("Name:%s, SNo:%d\n", Stu.name, Stu.sno);

If you define macros repeatedly, different compilers adopt different redefinition policies. Some compilers think this is wrong, while others just warn. The second approach is used in Xcode. Such as:

#define M 5                 //macro definition
#define m               //redefine, Warning: ... main.c:26:9: ' m ' macro redefined

These simple macros are used primarily to define those explicit constants (Manifest Constants) (Stephen prata,2004) and make the program easier to modify, especially if a constant value is used more than once in a program, just change a macro definition. All values in the program that appear in the variable can be changed. And there are many other advantages to the macro definition, such as making the program easier to understand, control conditional compilation, and so on.

The difference between #define and #typedef:
Both can be used to represent data types, such as:

#define INT1 int
typedef int INT2;

The two are equivalent and the invocation is the same:

INT1 a1 = 3;
INT2 A2 = 5;

But the problem comes when you use the following:

#define INT1 int *
typedef int * INT2;
INT1 A1, B1;
INT2 A2, B2;
B1 = &m;         ... Main.c:185:8: incompatible pointer to the integer conversion assigning to ' int ' from ' int * '; Remove &
b2 = &n;         Ok

Because INT1 A1, B1; After the substitution of the macro is: int * A1, B1; That is, a pointer to an int variable and a variable b1 of type int is defined. INT2 A2, B2; the definition is two variables A2 and B2, both of which are of type INT2, i.e. int *, So two are pointers to int-type variables.
So the difference is that the macro definition is simply a string substitution, which is done in the preprocessing phase. Instead of a simple string substitution, Typede can be used to rename the type descriptor, and the alias of the type can have the function of a type definition description, which is done at compile time.

2, has the parameter macro

    C language macros can have parameters, such macros become the shape and function similar to the class function macro (function-like macro), such as:

Macro Call:
Macro name (actual parameter list);
printf ("MEAN =%d\n", MEAN (7, 9)); Output Result: MEAN = 8

Like functions, the parameters in the macro definition become formal arguments, and the arguments in the macro call become actual arguments.
And unlike a parameterless macro, a parameter macro, in a call, not only expands the macro, but also replaces the formal parameter with the argument. Such as:

#define M 5                          //no parameter Macro
#define COUNT (m) m * m               //has parametric macro
printf ("Count =%d\n", count);   To be replaced by: Count = ten
                                     //output Result: Count = 100

This seems to be similar to a function call, but in fact there is a big difference. Such as:

#define COUNT (M) m * m               //defines a parameter macro
int x = 6;
printf ("Count =%d\n", count (x + 1));//Output Result: Count =
printf ("Count =%d\n", Count (++x))  ; Output result: COUNT =                                                                                               //warning: ... main.c:161:34:multiple unsequenced             modifications to ' x '

These two results differ greatly from the result of the method that invokes the function, because if it is like a function, count (x + 1) should be the equivalent of Count (7), and the result should be 7 * 7 = 49, but the output is 21. The reason is that the preprocessor does not perform technology, it is only for string substitution, and it does not automatically enclose parentheses (), so count (x + 1) is replaced with count (x + 1 * x + 1), substituting x = 6, which is 6 + 1 * 6 + 1 = 13. The solution is to use parentheses to enclose the entire replacement text and each parameter in it:

#define COUNT (M) ((m)  

But even with parentheses, it does not solve the last case of the above example, COUNT (++x) is replaced with ++x * ++x, which is 7 * 8 = 56, instead of 7 * 7 = 49, the simplest solution is to not use the "+ +", "–" or "+ +" in a parametric macro.

It says that the macro name can not have spaces, the macro name and the formal parameter list can not have spaces between the parameters, and the formal parameter list between the parameters may appear spaces:

#define SUM (a,b) A + B              //define a parametric macro
printf ("sum =%d\n", sum (1,2));      Invokes a parameter macro. Build Failed.
because SUM is replaced by: (A,B) A + b

If you use a function to find the square of an integer, you are:

int count (int x) {return
    x * x;
}

So in the macro definition: The parameters in #define COUNT (m) m * m do not allocate memory cells, so they are not defined as types. In the function int count (int x), the formal parameter is a local variable that allocates a memory cell in the stack, so it is defined as a type and is "value pass" between the actual participating parameters. But the macro is only symbolic substitution, there is no value transfer.

A macro definition can also be used to define an expression or multiple statements. Such as:

#define JI (a,b) A = i + 3; B = j + 5;   Macros define multiple statements
int i = 5, j = Ten;
int m = 0, n = 0;
JI (M, n);                               The macro substitution is: M = i + 3, n = j + 5;
printf ("M =%d, n =%d\n", m, n);       The output is: M = 8, n = 15

3, # operator

For example, if we define a macro:

We want to output "1 + 2 + 3 + 4 = 10", which is cumbersome in the following ways, with duplicate code and parentheses in the middle:

printf ("(%d +%d) + (%d +%d) =%d\n", 1, 2, 3, 4, SUM (1 + 2, 3+ 4));

Then consider using the # operator to include the macro parameter in the string, which is useful for converting the language symbol into a string. For example, if A is a macro parameter, the #a in the replacement text is converted to "a" by the system. And the process of transformation becomes "stringizing". Use this method to achieve the above requirements:

#define SUM (a,b) printf (#a "+" #b "=%d\n", ((a) + (b)))    //macro definition, using the # operator
SUM (1 + 2, 3 + 4);                                          Macro call
//Output Result: 1 + 2 + 3 + 4 = 10

When calling macros, replace a with 1 + 2, with 3 + 4 instead of B, the replacement text is: printf ("1 + 2" "+" "3 + 4" =%d\n, ((1 + 2) + (3 + 4)), then the string concatenation function converts four adjacent strings to one character String:

"1 + 2 + 3 + 4 =%d\n"

4, # # operator

Like the # operator, the # # operator can also be used in alternate text, and its role is to bind, combining two language symbols into a single language symbol, which is also known as the "preprocessor binder (Preprocessor Glue)". Usage:

#define NAME (n) Num # # N            //macro definition, use # # operator
int NUM0 =;
printf ("NUM0 =%d\n", NAME (0));     Macro Call

NAME (0) is replaced with Num # # 0, which is bonded to: NUM0.

5, variable macros: ... and __va_args__

We often want to output the results by using Prinf ("...", ...) more than once; If you use the above example #define SUM (a,b) printf (#a "+" #b "=%d\n", ((a) + (b)), the format is fixed and cannot be used to output other formats.
At this point we can consider using variable macros (variadic Macros). Usage is:

#define PR (...) printf (__va_args__)     //Macro definition
PR ("hello\n");                          Macro call
//output Result: Hello

In a macro definition, the last argument in the formal parameter list is the ellipsis "...", and "__va_args__" can be used in the replacement text to represent the ellipsis "...". And the above example macro substitution is: printf ("hello\n");

There is also an example:

#define PR2 (X, ...) printf ("Message" #X: "__va_args__)   //macro definition
double msg = ten;
PR2 (1, "msg =%.2f\n", msg);                            Macro call
//output result: Message1:msg = 10.00

In a macro invocation, the value of X is 10, so the #X is replaced with "1". After the macro substitution is:

printf ("Message" "1" ":" "msg =%.2f\n", msg);

Then these 4 strings are concatenated into one:

printf ("message1:msg =%.2f\n", msg);

Note that the ellipsis "..." can only be used to replace the last one in the parameter list of the macro.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.