1. Macros contain special symbols

There are several types: #, ##, \

1.1 String-like Operator (#)

Using a # in front of an argument in a macro, the preprocessor will convert the argument to an array of characters, in other words: # means “stringing”, and # appears in the macro definition to convert the following argument to a string.

Note: This can only be used in macro definitions with passed parameters and must precede the parameter name in the macro definition body.

Such as:

#define exp(s) printf("test s is:%s\n",s)
#define exp1(s) printf("test s is:%s\n",#s)
#define exp2(s) #s 
int main(a) {
    exp("hello");
    exp1(hello);

    string str = exp2(   bac );
    cout<<str<<""<<str.size()<<endl;
    /** * ignores the Spaces before and after the passed parameter name. * /
    string str1 = exp2( asda  bac );
    /** * The compiler automatically concatenates substrings when there is a space between each argument name. * Concatenates each substring with a space between them, ignoring the remaining Spaces. * /
    cout<<str1<<""<<str1.size()<<endl;
    return 0;
}
Copy the code

The code above shows the basic usage and whitespace handling rules. The whitespace handling rules are as follows:

Ignores the Spaces before and after the passed parameter name.

string str = exp2(   bac );
cout<<str<<""<<str.size()<<endl; //bac 3
Copy the code

When there is a space between the parameter names, the compiler will automatically concatenate the substrings, concatenating each substring with a space between them, ignoring the remaining Spaces.

string str1 = exp2( asda  bac );
cout<<str1<<""<<str1.size()<<endl; //asda bac 8
Copy the code

1.2 Symbolic Join operator (##)

“##” is a separate connection mode, which is used to separate and then enforce the connection. Converts multiple parameters defined by the macro to an actual parameter name.

Matters needing attention:

(1) When using ## to connect parameters, Spaces before and after ## are optional.

(2) The actual parameter name after the connection must be the actual parameter name or the macro definition known by the compiler.

(3) ## prevents the macro from expanding if the parameter after ## is itself a macro.

Example:

#define expA(s) printf("The prefixed string is :%s\n",gc_##s)  //gc_s must exist
// Note 2
#define expB(s) printf("The prefixed string is :%s\n",gc_  ##  s)  //gc_s must exist
// Note 1
#define gc_hello1 "I am gc_hello1"
int main(a) {
    // Note 1
    const char * gc_hello = "I am gc_hello";
    expA(hello); // I am gc_hello
    expB(hello1); // I am gc_hello1 
}
Copy the code

1.3 Line continuation Operator (\)

When a defined macro cannot be completed on one line, use “\” to continue the macro definition on the next line.

Note the space before \.

#define MAX(a,b) ((a)>(b) ? (a) (b)) int main() {int max_val = MAX(3,6); cout<

2.do{… The use of} while (0)

2.1 Avoid semantic misinterpretation

Such as:

#definefun() f1(); f2();
if(a>0)
    fun(a)Copy the code

The macro expands to read:

if(a>0)
    f1(a);f2(a);Copy the code

A >0 executes f1 and F2, but f2 executes every time, so it’s wrong.

To solve this problem, {} blocks are often used when writing code.

Such as:

#definefun() {f1(); f2(); }
if(a>0)
    fun(a);/ / macro expansion
if(a>0)
{
    f1(a);f2(a); };Copy the code

However, you will find that the syntax is not correct because the macro is expanded with a semicolon. (Although the compilation runs fine, normal no semicolons). So the best thing to do is this

#define fun() \
    do { \
        f1(); \
        f2(); \
    } while(0) \
Copy the code

If you develop a library, or even just a macro implementation for others to use, you can’t be sure that everyone will use the implementation the way you intended. Some users will double parentheses everywhere, and others will assume you’ll handle it. So you need to make sure that your implementation behaves consistently across usage scenarios. Also, as Scott Meyers talked about in Effective C++, make interfaces easy to use correctly and hard to misuse.

2.2 Avoiding goto control flow ¶

In some functions, we may need to do some cleaning before the return statement, such as freeing the memory requested by malloc at the beginning of the function. Using goto is always an easy way to do this:

int f(a) {
    int *p = (int *)malloc(sizeof(int));
    *p = 10; 
    cout<<*p<<endl;
#ifndef DEBUG
    int error=1;
#endif
    if(error)
        goto END;
    // dosomething
END:
    cout<<"free"<<endl;
    free(p);
    return 0;
}
Copy the code

However, because goto does not conform to the structure of software engineering and can make the code difficult to understand, many people do not advocate using it. In this case, we can use do{… }while(0) to do the same:

int ff(a) {
    int *p = (int *)malloc(sizeof(int));
    *p = 10; 
    cout<<*p<<endl;
    do{ 
#ifndef DEBUG
        int error=1;
#endif
        if(error)
            break;
        //dosomething
    }while(0);
    cout<<"free"<<endl;
    free(p);
    return 0;
}
Copy the code

Here we use do{… } include while(0), use break instead of goto, subsequent cleanup after while now achieves the same effect, and the code is much more readable and maintainable than the goto code above.

2.3 Avoid macro warnings

Empty macros are often used in the kernel due to the limitations of different architectures. At compile time, these null macros give warnings. To avoid such warnings, use do{… }while(0) to define a null macro:

#define EMPTYMICRO do{}while(0)
Copy the code

2.4 Define a single block of functions to perform complex operations

If you have a complex function with lots of variables and you don’t want to add new functions, use do{… }while(0), write your code in there, where you can define variables without worrying about the names of variables repeating before or after the function. In this case, the same variable is used in multiple places (but each place has a different meaning). We can narrow the scope in each do-while, for example:

int fc(a)
{
    int k1 = 10;
    cout<<k1<<endl;
    do{
        int k1 = 100;
        cout<<k1<<endl;
    }while(0);
    cout<<k1<<endl;
}
Copy the code

Study article:

1. Light – city. Club/sc/basic_co… 2. www.cnblogs.com/lizhenghn/p…